diff options
author | Martin Schanzenbach <mschanzenbach@posteo.de> | 2016-01-08 18:59:47 +0000 |
---|---|---|
committer | Martin Schanzenbach <mschanzenbach@posteo.de> | 2016-01-08 18:59:47 +0000 |
commit | 35262a0fe27afccb154122f113adcc75947ee45d (patch) | |
tree | 5b1259067c9da96e60c2a303415b222a4c383319 /src/identity-provider/identity_provider_api.c | |
parent | 1b67c9c5424c96ff4e30d12b8d58cec315f000a1 (diff) | |
download | gnunet-35262a0fe27afccb154122f113adcc75947ee45d.tar.gz gnunet-35262a0fe27afccb154122f113adcc75947ee45d.zip |
- More heavy refactoring. Probably lots of broken things to see here.
Diffstat (limited to 'src/identity-provider/identity_provider_api.c')
-rw-r--r-- | src/identity-provider/identity_provider_api.c | 611 |
1 files changed, 611 insertions, 0 deletions
diff --git a/src/identity-provider/identity_provider_api.c b/src/identity-provider/identity_provider_api.c new file mode 100644 index 000000000..c22151534 --- /dev/null +++ b/src/identity-provider/identity_provider_api.c | |||
@@ -0,0 +1,611 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | Copyright (C) 2016 Christian Grothoff (and other contributing authors) | ||
4 | |||
5 | GNUnet is free software; you can redistribute it and/or modify | ||
6 | it under the terms of the GNU General Public Liceidentity as published | ||
7 | by the Free Software Foundation; either version 3, or (at your | ||
8 | option) any later version. | ||
9 | |||
10 | GNUnet is distributed in the hope that it will be useful, but | ||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | General Public Liceidentity for more details. | ||
14 | |||
15 | You should have received a copy of the GNU General Public Liceidentity | ||
16 | along with GNUnet; see the file COPYING. If not, write to the | ||
17 | Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, | ||
18 | Boston, MA 02110-1301, USA. | ||
19 | */ | ||
20 | |||
21 | /** | ||
22 | * @file identity-provider/identity_provider_api.c | ||
23 | * @brief api to interact with the identity provider service | ||
24 | * @author Martin Schanzenbach | ||
25 | */ | ||
26 | #include "platform.h" | ||
27 | #include "gnunet_util_lib.h" | ||
28 | #include "gnunet_constants.h" | ||
29 | #include "gnunet_protocols.h" | ||
30 | #include "gnunet_identity_provider_service.h" | ||
31 | #include "identity_provider.h" | ||
32 | |||
33 | #define LOG(kind,...) GNUNET_log_from (kind, "identity-api",__VA_ARGS__) | ||
34 | |||
35 | |||
36 | |||
37 | /** | ||
38 | * Handle for an operation with the service. | ||
39 | */ | ||
40 | struct GNUNET_IDENTITY_PROVIDER_Operation | ||
41 | { | ||
42 | |||
43 | /** | ||
44 | * Main handle. | ||
45 | */ | ||
46 | struct GNUNET_IDENTITY_PROVIDER_Handle *h; | ||
47 | |||
48 | /** | ||
49 | * We keep operations in a DLL. | ||
50 | */ | ||
51 | struct GNUNET_IDENTITY_PROVIDER_Operation *next; | ||
52 | |||
53 | /** | ||
54 | * We keep operations in a DLL. | ||
55 | */ | ||
56 | struct GNUNET_IDENTITY_PROVIDER_Operation *prev; | ||
57 | |||
58 | /** | ||
59 | * Message to send to the service. | ||
60 | * Allocated at the end of this struct. | ||
61 | */ | ||
62 | const struct GNUNET_MessageHeader *msg; | ||
63 | |||
64 | /** | ||
65 | * Continuation to invoke with the result of the transmission; @e cb | ||
66 | * will be NULL in this case. | ||
67 | */ | ||
68 | GNUNET_IDENTITY_PROVIDER_ExchangeCallback ex_cb; | ||
69 | |||
70 | /** | ||
71 | * Continuation to invoke with the result of the transmission for | ||
72 | * 'issue' operations (@e cont will be NULL in this case). | ||
73 | */ | ||
74 | GNUNET_IDENTITY_PROVIDER_IssueCallback iss_cb; | ||
75 | |||
76 | /** | ||
77 | * Closure for @e cont or @e cb. | ||
78 | */ | ||
79 | void *cls; | ||
80 | |||
81 | }; | ||
82 | |||
83 | |||
84 | /** | ||
85 | * Handle for the service. | ||
86 | */ | ||
87 | struct GNUNET_IDENTITY_PROVIDER_Handle | ||
88 | { | ||
89 | /** | ||
90 | * Configuration to use. | ||
91 | */ | ||
92 | const struct GNUNET_CONFIGURATION_Handle *cfg; | ||
93 | |||
94 | /** | ||
95 | * Socket (if available). | ||
96 | */ | ||
97 | struct GNUNET_CLIENT_Connection *client; | ||
98 | |||
99 | /** | ||
100 | * Function to call when we receive updates. | ||
101 | */ | ||
102 | GNUNET_IDENTITY_PROVIDER_Callback cb; | ||
103 | |||
104 | /** | ||
105 | * Closure for 'cb'. | ||
106 | */ | ||
107 | void *cb_cls; | ||
108 | |||
109 | /** | ||
110 | * Head of active operations. | ||
111 | */ | ||
112 | struct GNUNET_IDENTITY_PROVIDER_Operation *op_head; | ||
113 | |||
114 | /** | ||
115 | * Tail of active operations. | ||
116 | */ | ||
117 | struct GNUNET_IDENTITY_PROVIDER_Operation *op_tail; | ||
118 | |||
119 | /** | ||
120 | * Currently pending transmission request, or NULL for none. | ||
121 | */ | ||
122 | struct GNUNET_CLIENT_TransmitHandle *th; | ||
123 | |||
124 | /** | ||
125 | * Task doing exponential back-off trying to reconnect. | ||
126 | */ | ||
127 | struct GNUNET_SCHEDULER_Task * reconnect_task; | ||
128 | |||
129 | /** | ||
130 | * Time for next connect retry. | ||
131 | */ | ||
132 | struct GNUNET_TIME_Relative reconnect_delay; | ||
133 | |||
134 | /** | ||
135 | * Are we polling for incoming messages right now? | ||
136 | */ | ||
137 | int in_receive; | ||
138 | |||
139 | }; | ||
140 | |||
141 | |||
142 | /** | ||
143 | * Try again to connect to the service. | ||
144 | * | ||
145 | * @param cls handle to the service. | ||
146 | * @param tc scheduler context | ||
147 | */ | ||
148 | static void | ||
149 | reconnect (void *cls, | ||
150 | const struct GNUNET_SCHEDULER_TaskContext *tc); | ||
151 | |||
152 | |||
153 | /** | ||
154 | * Reschedule a connect attempt to the service. | ||
155 | * | ||
156 | * @param h transport service to reconnect | ||
157 | */ | ||
158 | static void | ||
159 | reschedule_connect (struct GNUNET_IDENTITY_Handle *h) | ||
160 | { | ||
161 | GNUNET_assert (h->reconnect_task == NULL); | ||
162 | |||
163 | if (NULL != h->th) | ||
164 | { | ||
165 | GNUNET_CLIENT_notify_transmit_ready_cancel (h->th); | ||
166 | h->th = NULL; | ||
167 | } | ||
168 | if (NULL != h->client) | ||
169 | { | ||
170 | GNUNET_CLIENT_disconnect (h->client); | ||
171 | h->client = NULL; | ||
172 | } | ||
173 | h->in_receive = GNUNET_NO; | ||
174 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
175 | "Scheduling task to reconnect to identity provider service in %s.\n", | ||
176 | GNUNET_STRINGS_relative_time_to_string (h->reconnect_delay, GNUNET_YES)); | ||
177 | h->reconnect_task = | ||
178 | GNUNET_SCHEDULER_add_delayed (h->reconnect_delay, &reconnect, h); | ||
179 | h->reconnect_delay = GNUNET_TIME_STD_BACKOFF (h->reconnect_delay); | ||
180 | } | ||
181 | |||
182 | |||
183 | /** | ||
184 | * Type of a function to call when we receive a message | ||
185 | * from the service. | ||
186 | * | ||
187 | * @param cls closure | ||
188 | * @param msg message received, NULL on timeout or fatal error | ||
189 | */ | ||
190 | static void | ||
191 | message_handler (void *cls, | ||
192 | const struct GNUNET_MessageHeader *msg) | ||
193 | { | ||
194 | struct GNUNET_IDENTITY_PROVIDER_Handle *h = cls; | ||
195 | struct GNUNET_IDENTITY_PROVIDER_Operation *op; | ||
196 | struct GNUNET_IDENTITY_PROVIDER_Token token; | ||
197 | struct GNUNET_IDENTITY_PROVIDER_Ticket ticket; | ||
198 | const struct GNUNET_IDENTITY_PROVIDER_IssueResultMessage *irm; | ||
199 | const struct GNUNET_IDENTITY_ExchangeResultMessage *erm; | ||
200 | struct GNUNET_CRYPTO_EcdsaPublicKey pub; | ||
201 | struct GNUNET_HashCode id; | ||
202 | const char *str; | ||
203 | uint16_t size; | ||
204 | uint16_t name_len; | ||
205 | |||
206 | if (NULL == msg) | ||
207 | { | ||
208 | reschedule_connect (h); | ||
209 | return; | ||
210 | } | ||
211 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
212 | "Received message of type %d from identity provider service\n", | ||
213 | ntohs (msg->type)); | ||
214 | size = ntohs (msg->size); | ||
215 | switch (ntohs (msg->type)) | ||
216 | { | ||
217 | case GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ISSUE_RESULT: | ||
218 | if (size < sizeof (struct GNUNET_IDENTITY_IssueResultMessage)) | ||
219 | { | ||
220 | GNUNET_break (0); | ||
221 | reschedule_connect (h); | ||
222 | return; | ||
223 | } | ||
224 | irm = (const struct GNUNET_IDENTITY_IssueResultMessage *) msg; | ||
225 | str = (const char *) &irm[1]; | ||
226 | if ( (size > sizeof (struct GNUNET_IDENTITY_IssueResultMessage)) && | ||
227 | ('\0' != str[size - sizeof (struct GNUNET_IDENTITY_IssueResultMessage) - 1]) ) | ||
228 | { | ||
229 | GNUNET_break (0); | ||
230 | reschedule_connect (h); | ||
231 | return; | ||
232 | } | ||
233 | if (size == sizeof (struct GNUNET_IDENTITY_IssueResultMessage)) | ||
234 | str = NULL; | ||
235 | |||
236 | op = h->op_head; | ||
237 | GNUNET_CONTAINER_DLL_remove (h->op_head, | ||
238 | h->op_tail, | ||
239 | op); | ||
240 | GNUNET_CLIENT_receive (h->client, &message_handler, h, | ||
241 | GNUNET_TIME_UNIT_FOREVER_REL); | ||
242 | ticket->data = str; | ||
243 | if (NULL != op->iss_cb) | ||
244 | op->iss_cb (op->cls, &ticket); | ||
245 | GNUNET_free (op); | ||
246 | break; | ||
247 | case GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_EXCHANGE_RESULT: | ||
248 | if (size < sizeof (struct GNUNET_IDENTITY_ExchangeResultMessage)) | ||
249 | { | ||
250 | GNUNET_break (0); | ||
251 | reschedule_connect (h); | ||
252 | return; | ||
253 | } | ||
254 | erm = (const struct GNUNET_IDENTITY_ExchangeResultMessage *) msg; | ||
255 | str = (const char *) &erm[1]; | ||
256 | if ( (size > sizeof (struct GNUNET_IDENTITY_ExchangeResultMessage)) && | ||
257 | ('\0' != str[size - sizeof (struct GNUNET_IDENTITY_ExchangeResultMessage) - 1]) ) | ||
258 | { | ||
259 | GNUNET_break (0); | ||
260 | reschedule_connect (h); | ||
261 | return; | ||
262 | } | ||
263 | if (size == sizeof (struct GNUNET_IDENTITY_ExchangeResultMessage)) | ||
264 | str = NULL; | ||
265 | |||
266 | op = h->op_head; | ||
267 | GNUNET_CONTAINER_DLL_remove (h->op_head, | ||
268 | h->op_tail, | ||
269 | op); | ||
270 | GNUNET_CLIENT_receive (h->client, &message_handler, h, | ||
271 | GNUNET_TIME_UNIT_FOREVER_REL); | ||
272 | token->data = str; | ||
273 | if (NULL != op->ex_cb) | ||
274 | op->ex_cb (op->cls, token); | ||
275 | GNUNET_free (op); | ||
276 | break; | ||
277 | |||
278 | default: | ||
279 | GNUNET_break (0); | ||
280 | reschedule_connect (h); | ||
281 | return; | ||
282 | } | ||
283 | } | ||
284 | |||
285 | |||
286 | /** | ||
287 | * Schedule transmission of the next message from our queue. | ||
288 | * | ||
289 | * @param h identity handle | ||
290 | */ | ||
291 | static void | ||
292 | transmit_next (struct GNUNET_IDENTITY_PROVIDER_Handle *h); | ||
293 | |||
294 | |||
295 | /** | ||
296 | * Transmit next message to service. | ||
297 | * | ||
298 | * @param cls the `struct GNUNET_IDENTITY_PROVIDER_Handle`. | ||
299 | * @param size number of bytes available in @a buf | ||
300 | * @param buf where to copy the message | ||
301 | * @return number of bytes copied to buf | ||
302 | */ | ||
303 | static size_t | ||
304 | send_next_message (void *cls, | ||
305 | size_t size, | ||
306 | void *buf) | ||
307 | { | ||
308 | struct GNUNET_IDENTITY_PROVIDER_Handle *h = cls; | ||
309 | struct GNUNET_IDENTITY_PROVIDER_Operation *op = h->op_head; | ||
310 | size_t ret; | ||
311 | |||
312 | h->th = NULL; | ||
313 | if (NULL == op) | ||
314 | return 0; | ||
315 | ret = ntohs (op->msg->size); | ||
316 | if (ret > size) | ||
317 | { | ||
318 | reschedule_connect (h); | ||
319 | return 0; | ||
320 | } | ||
321 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
322 | "Sending message of type %d to identity provider service\n", | ||
323 | ntohs (op->msg->type)); | ||
324 | memcpy (buf, op->msg, ret); | ||
325 | if ( (NULL == op->cont) && | ||
326 | (NULL == op->cb) ) | ||
327 | { | ||
328 | GNUNET_CONTAINER_DLL_remove (h->op_head, | ||
329 | h->op_tail, | ||
330 | op); | ||
331 | GNUNET_free (op); | ||
332 | transmit_next (h); | ||
333 | } | ||
334 | if (GNUNET_NO == h->in_receive) | ||
335 | { | ||
336 | h->in_receive = GNUNET_YES; | ||
337 | GNUNET_CLIENT_receive (h->client, | ||
338 | &message_handler, h, | ||
339 | GNUNET_TIME_UNIT_FOREVER_REL); | ||
340 | } | ||
341 | return ret; | ||
342 | } | ||
343 | |||
344 | |||
345 | /** | ||
346 | * Schedule transmission of the next message from our queue. | ||
347 | * | ||
348 | * @param h identity provider handle | ||
349 | */ | ||
350 | static void | ||
351 | transmit_next (struct GNUNET_IDENTITY_PROVIDER_Handle *h) | ||
352 | { | ||
353 | struct GNUNET_IDENTITY_PROVIDER_Operation *op = h->op_head; | ||
354 | |||
355 | GNUNET_assert (NULL == h->th); | ||
356 | if (NULL == op) | ||
357 | return; | ||
358 | if (NULL == h->client) | ||
359 | return; | ||
360 | h->th = GNUNET_CLIENT_notify_transmit_ready (h->client, | ||
361 | ntohs (op->msg->size), | ||
362 | GNUNET_TIME_UNIT_FOREVER_REL, | ||
363 | GNUNET_NO, | ||
364 | &send_next_message, | ||
365 | h); | ||
366 | } | ||
367 | |||
368 | |||
369 | /** | ||
370 | * Try again to connect to the service. | ||
371 | * | ||
372 | * @param cls handle to the identity provider service. | ||
373 | * @param tc scheduler context | ||
374 | */ | ||
375 | static void | ||
376 | reconnect (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
377 | { | ||
378 | struct GNUNET_IDENTITY_Handle *h = cls; | ||
379 | struct GNUNET_IDENTITY_Operation *op; | ||
380 | struct GNUNET_MessageHeader msg; | ||
381 | |||
382 | h->reconnect_task = NULL; | ||
383 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
384 | "Connecting to identity provider service.\n"); | ||
385 | GNUNET_assert (NULL == h->client); | ||
386 | h->client = GNUNET_CLIENT_connect ("identity-provider", h->cfg); | ||
387 | GNUNET_assert (NULL != h->client); | ||
388 | if ( (NULL == h->op_head) || | ||
389 | (GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_START != ntohs (h->op_head->msg->type)) ) | ||
390 | { | ||
391 | op = GNUNET_malloc (sizeof (struct GNUNET_IDENTITY_PROVIDER_Operation) + | ||
392 | sizeof (struct GNUNET_MessageHeader)); | ||
393 | op->h = h; | ||
394 | op->msg = (const struct GNUNET_MessageHeader *) &op[1]; | ||
395 | msg.size = htons (sizeof (msg)); | ||
396 | msg.type = htons (GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_START); | ||
397 | memcpy (&op[1], &msg, sizeof (msg)); | ||
398 | GNUNET_CONTAINER_DLL_insert (h->op_head, | ||
399 | h->op_tail, | ||
400 | op); | ||
401 | } | ||
402 | transmit_next (h); | ||
403 | GNUNET_assert (NULL != h->th); | ||
404 | } | ||
405 | |||
406 | |||
407 | /** | ||
408 | * Connect to the identity provider service. | ||
409 | * | ||
410 | * @param cfg the configuration to use | ||
411 | * @return handle to use | ||
412 | */ | ||
413 | struct GNUNET_IDENTITY_PROVIDER_Handle * | ||
414 | GNUNET_IDENTITY_PROVIDER_connect (const struct GNUNET_CONFIGURATION_Handle *cfg) | ||
415 | { | ||
416 | struct GNUNET_IDENTITY_PROVIDER_Handle *h; | ||
417 | |||
418 | h = GNUNET_new (struct GNUNET_IDENTITY_PROVIDER_Handle); | ||
419 | h->cfg = cfg; | ||
420 | h->cb = cb; | ||
421 | h->cb_cls = cb_cls; | ||
422 | h->egos = GNUNET_CONTAINER_multihashmap_create (16, GNUNET_YES); | ||
423 | h->reconnect_delay = GNUNET_TIME_UNIT_ZERO; | ||
424 | h->reconnect_task = GNUNET_SCHEDULER_add_now (&reconnect, h); | ||
425 | return h; | ||
426 | } | ||
427 | |||
428 | |||
429 | /** | ||
430 | * Issue an identity token | ||
431 | * | ||
432 | * @param id identity service to query | ||
433 | * @param service_name for which service is an identity wanted | ||
434 | * @param cb function to call with the result (will only be called once) | ||
435 | * @param cb_cls closure for @a cb | ||
436 | * @return handle to abort the operation | ||
437 | */ | ||
438 | struct GNUNET_IDENTITY_PROVIDER_Operation * | ||
439 | GNUNET_IDENTITY_PROVIDER_issue_token (struct GNUNET_IDENTITY_PROVIDER_Handle *id, | ||
440 | const struct GNUNET_CRYPTO_EcdsaPrivateKey *iss_key, | ||
441 | const struct GNUNET_CRYPTO_EcdsaPublicKey *aud_key, | ||
442 | const char* scopes, | ||
443 | const struct GNUNET_TIME_Absolute exp, | ||
444 | GNUNET_IDENTITY_PROVIDER_IssueCallback cb, | ||
445 | void *cb_cls) | ||
446 | { | ||
447 | struct GNUNET_IDENTITY_PROVIDER_Operation *op; | ||
448 | struct GNUNET_IDENTITY_PROVIDER_IssueMessage *im; | ||
449 | size_t slen; | ||
450 | |||
451 | slen = strlen (scopes) + 1; | ||
452 | if (slen >= GNUNET_SERVER_MAX_MESSAGE_SIZE - sizeof (struct GNUNET_IDENTITY_PROVIDER_IssueMessage)) | ||
453 | { | ||
454 | GNUNET_break (0); | ||
455 | return NULL; | ||
456 | } | ||
457 | op = GNUNET_malloc (sizeof (struct GNUNET_IDENTITY_PROVIDER_Operation) + | ||
458 | sizeof (struct GNUNET_IDENTITY_IssueMessage) + | ||
459 | slen); | ||
460 | op->h = id; | ||
461 | op->cb = cb; | ||
462 | op->cls = cb_cls; | ||
463 | im = (struct GNUNET_IDENTITY_GetDefaultMessage *) &op[1]; | ||
464 | im->header.type = htons (GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_ISSUE); | ||
465 | im->header.size = htons (sizeof (struct GNUNET_IDENTITY_PROVIDER_IssueMessage) + | ||
466 | slen); | ||
467 | im->iss_key = *iss_key; | ||
468 | im->aud_key = *aud_ley; | ||
469 | im->exp = exp.abs_value_ul; | ||
470 | memcpy (&im[1], scopes, slen); | ||
471 | op->msg = &im->header; | ||
472 | GNUNET_CONTAINER_DLL_insert_tail (id->op_head, | ||
473 | id->op_tail, | ||
474 | op); | ||
475 | if (NULL == id->th) | ||
476 | transmit_next (id); | ||
477 | return op; | ||
478 | } | ||
479 | |||
480 | |||
481 | /** | ||
482 | * Exchange a token ticket for a token | ||
483 | * | ||
484 | * @param id identity provider service | ||
485 | * @param ticket ticket to exchange | ||
486 | * @param cont function to call once the operation finished | ||
487 | * @param cont_cls closure for @a cont | ||
488 | * @return handle to abort the operation | ||
489 | */ | ||
490 | struct GNUNET_IDENTITY_PROVIDER_Operation * | ||
491 | GNUNET_IDENTITY_PROVIDER_exchange_ticket (struct GNUNET_IDENTITY_Handle *id, | ||
492 | const char *ticket, | ||
493 | GNUNET_IDENTITY_PROVIDER_ExchangeCallback cont, | ||
494 | void *cont_cls) | ||
495 | { | ||
496 | struct GNUNET_IDENTITY_PROVIDER_Operation *op; | ||
497 | struct GNUNET_IDENTITY_PROVIDER_ExchangeMessage *em; | ||
498 | size_t slen; | ||
499 | |||
500 | slen = strlen (ticket) + 1; | ||
501 | if (slen >= GNUNET_SERVER_MAX_MESSAGE_SIZE - sizeof (struct GNUNET_IDENTITY_ExchangeMessage)) | ||
502 | { | ||
503 | GNUNET_break (0); | ||
504 | return NULL; | ||
505 | } | ||
506 | op = GNUNET_malloc (sizeof (struct GNUNET_IDENTITY_PROVIDER_Operation) + | ||
507 | sizeof (struct GNUNET_IDENTITY_ExchangeMessage) + | ||
508 | slen); | ||
509 | op->h = id; | ||
510 | op->cont = cont; | ||
511 | op->cls = cont_cls; | ||
512 | em = (struct GNUNET_IDENTITY_ExchangeMessage *) &op[1]; | ||
513 | em->header.type = htons (GNUNET_MESSAGE_TYPE_IDENTITY_PROVIDER_EXCHANGE); | ||
514 | em->header.size = htons (sizeof (struct GNUNET_IDENTITY_ExchangeMessage) + | ||
515 | slen); | ||
516 | memcpy (&em[1], ticket, slen); | ||
517 | op->msg = &em->header; | ||
518 | GNUNET_CONTAINER_DLL_insert_tail (id->op_head, | ||
519 | id->op_tail, | ||
520 | op); | ||
521 | if (NULL == id->th) | ||
522 | transmit_next (id); | ||
523 | return op; | ||
524 | } | ||
525 | |||
526 | |||
527 | /** | ||
528 | * Cancel an operation. Note that the operation MAY still | ||
529 | * be executed; this merely cancels the continuation; if the request | ||
530 | * was already transmitted, the service may still choose to complete | ||
531 | * the operation. | ||
532 | * | ||
533 | * @param op operation to cancel | ||
534 | */ | ||
535 | void | ||
536 | GNUNET_IDENTITY_PROVIDER_cancel (struct GNUNET_IDENTITY_PROVIDER_Operation *op) | ||
537 | { | ||
538 | struct GNUNET_IDENTITY_Handle *h = op->h; | ||
539 | |||
540 | if ( (h->op_head != op) || | ||
541 | (NULL == h->client) ) | ||
542 | { | ||
543 | /* request not active, can simply remove */ | ||
544 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
545 | "Client aborted non-head operation, simply removing it\n"); | ||
546 | GNUNET_CONTAINER_DLL_remove (h->op_head, | ||
547 | h->op_tail, | ||
548 | op); | ||
549 | GNUNET_free (op); | ||
550 | return; | ||
551 | } | ||
552 | if (NULL != h->th) | ||
553 | { | ||
554 | /* request active but not yet with service, can still abort */ | ||
555 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
556 | "Client aborted head operation prior to transmission, aborting it\n"); | ||
557 | GNUNET_CLIENT_notify_transmit_ready_cancel (h->th); | ||
558 | h->th = NULL; | ||
559 | GNUNET_CONTAINER_DLL_remove (h->op_head, | ||
560 | h->op_tail, | ||
561 | op); | ||
562 | GNUNET_free (op); | ||
563 | transmit_next (h); | ||
564 | return; | ||
565 | } | ||
566 | /* request active with service, simply ensure continuations are not called */ | ||
567 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
568 | "Client aborted active request, NULLing continuation\n"); | ||
569 | op->ex_cb = NULL; | ||
570 | op->iss_cb = NULL; | ||
571 | } | ||
572 | |||
573 | |||
574 | /** | ||
575 | * Disconnect from service | ||
576 | * | ||
577 | * @param h handle to destroy | ||
578 | */ | ||
579 | void | ||
580 | GNUNET_IDENTITY_PROVIDER_disconnect (struct GNUNET_IDENTITY_PROVIDER_Handle *h) | ||
581 | { | ||
582 | struct GNUNET_IDENTITY_PROVIDER_Operation *op; | ||
583 | |||
584 | GNUNET_assert (NULL != h); | ||
585 | if (h->reconnect_task != NULL) | ||
586 | { | ||
587 | GNUNET_SCHEDULER_cancel (h->reconnect_task); | ||
588 | h->reconnect_task = NULL; | ||
589 | } | ||
590 | if (NULL != h->th) | ||
591 | { | ||
592 | GNUNET_CLIENT_notify_transmit_ready_cancel (h->th); | ||
593 | h->th = NULL; | ||
594 | } | ||
595 | while (NULL != (op = h->op_head)) | ||
596 | { | ||
597 | GNUNET_break (NULL == op->cont); | ||
598 | GNUNET_CONTAINER_DLL_remove (h->op_head, | ||
599 | h->op_tail, | ||
600 | op); | ||
601 | GNUNET_free (op); | ||
602 | } | ||
603 | if (NULL != h->client) | ||
604 | { | ||
605 | GNUNET_CLIENT_disconnect (h->client); | ||
606 | h->client = NULL; | ||
607 | } | ||
608 | GNUNET_free (h); | ||
609 | } | ||
610 | |||
611 | /* end of identity_provider_api.c */ | ||