aboutsummaryrefslogtreecommitdiff
path: root/src/scalarproduct/scalarproduct_api.c
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2013-08-23 13:42:15 +0000
committerChristian Grothoff <christian@grothoff.org>2013-08-23 13:42:15 +0000
commit33b89b07e0ea833955f64d07b7e54e64aab500e9 (patch)
treecfc01062d4d6951606b00bc62ac087ae78cb500c /src/scalarproduct/scalarproduct_api.c
parent22ab4538a2f7a21c0c831599a56d50c147de0ae5 (diff)
downloadgnunet-33b89b07e0ea833955f64d07b7e54e64aab500e9.tar.gz
gnunet-33b89b07e0ea833955f64d07b7e54e64aab500e9.zip
-more vector -> scalar renaming
Diffstat (limited to 'src/scalarproduct/scalarproduct_api.c')
-rw-r--r--src/scalarproduct/scalarproduct_api.c715
1 files changed, 715 insertions, 0 deletions
diff --git a/src/scalarproduct/scalarproduct_api.c b/src/scalarproduct/scalarproduct_api.c
new file mode 100644
index 000000000..4f8cde8fe
--- /dev/null
+++ b/src/scalarproduct/scalarproduct_api.c
@@ -0,0 +1,715 @@
1/*
2 This file is part of GNUnet.
3 (C) 2013 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 License as published
7 by the Free Software Foundation; either version 2, 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 License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
19 */
20
21/**
22 * @file vectorproduct/vectorproduct_api.c
23 * @brief API for the vectorproduct
24 * @author Christian Fuchs
25 * @author Gaurav Kukreja
26 *
27 */
28#include "platform.h"
29#include "gnunet_util_lib.h"
30#include "gnunet_statistics_service.h"
31#include "gnunet_vectorproduct_service.h"
32#include "gnunet_protocols.h"
33
34#define LOG(kind,...) GNUNET_log_from (kind, "vectorproduct-api",__VA_ARGS__)
35
36/**************************************************************
37 *** Datatype Declarations **********
38 **************************************************************/
39
40/**
41 * Entry in the request queue per client
42 */
43struct GNUNET_VECTORPRODUCT_QueueEntry
44{
45 /**
46 * This is a linked list.
47 */
48 struct GNUNET_VECTORPRODUCT_QueueEntry *next;
49
50 /**
51 * This is a linked list.
52 */
53 struct GNUNET_VECTORPRODUCT_QueueEntry *prev;
54
55 /**
56 * Handle to the master context.
57 */
58 struct GNUNET_VECTORPRODUCT_Handle *h;
59
60 /**
61 * Size of the message
62 */
63 uint16_t message_size;
64
65 /**
66 * Message to be sent to the vectorproduct service
67 */
68 struct GNUNET_VECTORPRODUCT_client_request* msg;
69
70 union
71 {
72 /**
73 * Function to call after transmission of the request.
74 */
75 GNUNET_VECTORPRODUCT_ContinuationWithStatus cont_status;
76
77 /**
78 * Function to call after transmission of the request.
79 */
80 GNUNET_VECTORPRODUCT_DatumProcessor cont_datum;
81 };
82
83 /**
84 * Closure for 'cont'.
85 */
86 void *cont_cls;
87
88 /**
89 * Has this message been transmitted to the service?
90 * Only ever GNUNET_YES for the head of the queue.
91 * Note that the overall struct should end at a
92 * multiple of 64 bits.
93 */
94 int16_t was_transmitted;
95
96 /**
97 * Timeout for the current operation.
98 */
99 struct GNUNET_TIME_Absolute timeout;
100
101 /**
102 * Task for timeout signaling.
103 */
104 GNUNET_SCHEDULER_TaskIdentifier timeout_task;
105
106 /**
107 * Response Processor for response from the service. This function calls the
108 * continuation function provided by the client.
109 */
110 GNUNET_VECTORPRODUCT_ResponseMessageHandler response_proc;
111};
112
113/**************************************************************
114 *** Function Declarations **********
115 **************************************************************/
116
117/**
118 * Creates a new entry at the tail of the DLL
119 *
120 * @param h handle to the master context
121 *
122 * @return pointer to the entry
123 */
124static struct GNUNET_VECTORPRODUCT_QueueEntry *
125make_queue_entry (struct GNUNET_VECTORPRODUCT_Handle *h);
126
127/**
128 * Removes the head entry from the queue
129 *
130 * @param h Handle to the master context
131 */
132static struct GNUNET_VECTORPRODUCT_QueueEntry *
133free_queue_head_entry (struct GNUNET_VECTORPRODUCT_Handle * h);
134
135/**
136 * Triggered when timeout occurs for a request in queue
137 *
138 * @param cls The pointer to the QueueEntry
139 * @param tc Task Context
140 */
141static void
142timeout_queue_entry (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc);
143
144/**
145 * Called when a response is received from the service. After basic check
146 * handler in qe->response_proc is called. This functions handles the response
147 * to the client which used the API.
148 *
149 * @param cls Pointer to the Master Context
150 * @param msg Pointer to the data received in response
151 */
152static void
153receive_cb (void *cls, const struct GNUNET_MessageHeader *msg);
154
155/**
156 * Transmits the request to the VectorProduct Sevice
157 *
158 * @param cls Closure
159 * @param size Size of the buffer
160 * @param buf Pointer to the buffer
161 *
162 * @return Size of the message sent
163 */
164static size_t transmit_request (void *cls, size_t size,
165 void *buf);
166
167/**
168 * Issues transmit request for the new entries in the queue
169 *
170 * @param h handle to the master context
171 */
172static void
173process_queue (struct GNUNET_VECTORPRODUCT_Handle *h);
174
175/**************************************************************
176 *** Static Function Declarations **********
177 **************************************************************/
178
179
180/**
181 * Creates a new entry at the tail of the DLL
182 *
183 * @param h handle to the master context
184 *
185 * @return pointer to the entry
186 */
187static struct GNUNET_VECTORPRODUCT_QueueEntry *
188make_queue_entry (struct GNUNET_VECTORPRODUCT_Handle *h)
189{
190 struct GNUNET_VECTORPRODUCT_QueueEntry *qe;
191
192 qe = GNUNET_new (struct GNUNET_VECTORPRODUCT_QueueEntry);
193
194 // if queue empty
195 if (NULL == h->queue_head && NULL == h->queue_tail)
196 {
197 qe->next = NULL;
198 qe->prev = NULL;
199 h->queue_head = qe;
200 h->queue_tail = qe;
201 }
202 else
203 {
204 qe->prev = h->queue_tail;
205 h->queue_tail->next = qe;
206 h->queue_tail = qe;
207 }
208
209 return qe;
210}
211
212
213/**
214 * Removes the head entry from the queue
215 *
216 * @param h Handle to the master context
217 */
218static struct GNUNET_VECTORPRODUCT_QueueEntry *
219free_queue_head_entry (struct GNUNET_VECTORPRODUCT_Handle * h)
220{
221 struct GNUNET_VECTORPRODUCT_QueueEntry * qe = NULL;
222
223 GNUNET_assert (NULL != h);
224 if (NULL == h->queue_head && NULL == h->queue_tail)
225 {
226 // The queue is empty. Just return.
227 LOG (GNUNET_ERROR_TYPE_DEBUG, "Queue was empty when free_queue_head_entry was called.\n");
228 }
229 else if (h->queue_head == h->queue_tail) //only one entry
230 {
231 qe = h->queue_head;
232 qe->next = NULL;
233 qe->prev = NULL;
234 h->queue_head = NULL;
235 h->queue_tail = NULL;
236 }
237 else
238 {
239 qe = h->queue_head;
240 h->queue_head = h->queue_head->next;
241 h->queue_head->prev = NULL;
242 qe->next = NULL;
243 qe->prev = NULL;
244 }
245 return qe;
246}
247
248
249/**
250 * Triggered when timeout occurs for a request in queue
251 *
252 * @param cls The pointer to the QueueEntry
253 * @param tc Task Context
254 */
255static void
256timeout_queue_entry (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
257{
258 struct GNUNET_VECTORPRODUCT_QueueEntry * qe = cls;
259
260 // Update Statistics
261 GNUNET_STATISTICS_update (qe->h->stats,
262 gettext_noop ("# queue entry timeouts"), 1,
263 GNUNET_NO);
264
265 // Clear the timeout_task
266 qe->timeout_task = GNUNET_SCHEDULER_NO_TASK;
267
268 // transmit_request is supposed to cancel timeout task.
269 // If message was not transmitted, there is definitely an error.
270 GNUNET_assert (GNUNET_NO == qe->was_transmitted);
271
272 LOG (GNUNET_ERROR_TYPE_INFO, "Timeout of request in datastore queue\n");
273
274 // remove the queue_entry for the queue
275 GNUNET_CONTAINER_DLL_remove (qe->h->queue_head, qe->h->queue_tail, qe);
276 qe->response_proc (qe, NULL, GNUNET_VECTORPRODUCT_Status_Timeout);
277}
278
279
280/**
281 * Handles the RESULT received in reply of prepare_response from the
282 * service
283 *
284 * @param cls Handle to the Master Context
285 * @param msg Pointer to the response received
286 */
287static void
288process_status_message (void *cls,
289 const struct GNUNET_MessageHeader *msg,
290 enum GNUNET_VECTORPRODUCT_ResponseStatus status)
291{
292 struct GNUNET_VECTORPRODUCT_QueueEntry *qe = cls;
293
294 GNUNET_assert (qe != NULL);
295
296 if (qe->cont_status != NULL)
297 qe->cont_status (qe->cont_cls, &qe->msg->key, status);
298}
299
300
301/**
302 * Handles the RESULT received in reply of prepare_response from the
303 * service
304 *
305 * @param cls Handle to the Master Context
306 * @param msg Pointer to the response received
307 */
308static void
309process_result_message (void *cls,
310 const struct GNUNET_MessageHeader *msg,
311 enum GNUNET_VECTORPRODUCT_ResponseStatus status)
312{
313 struct GNUNET_VECTORPRODUCT_QueueEntry *qe = cls;
314
315 GNUNET_assert (qe != NULL);
316
317 if (msg == NULL && qe->cont_datum != NULL)
318 {
319 LOG (GNUNET_ERROR_TYPE_DEBUG, "Timeout reached or session terminated.\n");
320 }
321 if (qe->cont_datum != NULL)
322 {
323 qe->cont_datum (qe->cont_cls, &qe->msg->key, &qe->msg->peer, status, (struct GNUNET_VECTORPRODUCT_client_response *) msg);
324 }
325}
326
327
328/**
329 * Called when a response is received from the service. After basic check
330 * handler in qe->response_proc is called. This functions handles the response
331 * to the client which used the API.
332 *
333 * @param cls Pointer to the Master Context
334 * @param msg Pointer to the data received in response
335 */
336static void
337receive_cb (void *cls, const struct GNUNET_MessageHeader *msg)
338{
339 struct GNUNET_VECTORPRODUCT_Handle *h = cls;
340 struct GNUNET_VECTORPRODUCT_QueueEntry *qe;
341 int16_t was_transmitted;
342 struct GNUNET_VECTORPRODUCT_client_response *message =
343 (struct GNUNET_VECTORPRODUCT_client_response *) msg;
344
345 h->in_receive = GNUNET_NO;
346 LOG (GNUNET_ERROR_TYPE_DEBUG, "Received reply from VectorProduct\n");
347
348 if (NULL == (qe = free_queue_head_entry (h)))
349 {
350 /**
351 * The queue head will be NULL if the client disconnected,
352 * * In case of Alice, client disconnected after sending request, before receiving response
353 * * In case of Bob, client disconnected after preparing response, before getting request from Alice.
354 */
355 process_queue (h);
356 return;
357 }
358
359 if (h->client == NULL)
360 {
361 // GKUKREJA : handle this correctly
362 /**
363 * The queue head will be NULL if the client disconnected,
364 * * In case of Alice, client disconnected after sending request, before receiving response
365 * * In case of Bob, client disconnected after preparing response, before getting request from Alice.
366 */
367 process_queue (h);
368 return;
369 }
370
371 was_transmitted = qe->was_transmitted;
372 // Control will only come here, when the request was transmitted to service,
373 // and service responded.
374 GNUNET_assert (was_transmitted == GNUNET_YES);
375
376 if (msg == NULL)
377 {
378 LOG (GNUNET_ERROR_TYPE_WARNING, "Service responded with NULL!\n");
379 qe->response_proc (qe, NULL, GNUNET_VECTORPRODUCT_Status_Failure);
380 }
381 else if ((ntohs (msg->type) != GNUNET_MESSAGE_TYPE_VECTORPRODUCT_SERVICE_TO_CLIENT))
382 {
383 LOG (GNUNET_ERROR_TYPE_WARNING, "Invalid Message Received\n");
384 qe->response_proc (qe, msg, GNUNET_VECTORPRODUCT_Status_InvalidResponse);
385 }
386 else if (ntohl (message->product_length) == 0)
387 {
388 // response for the responder client, successful
389 GNUNET_STATISTICS_update (h->stats,
390 gettext_noop ("# SUC responder result messages received"), 1,
391 GNUNET_NO);
392
393 LOG (GNUNET_ERROR_TYPE_DEBUG, "Received message from service without product attached.\n");
394 qe->response_proc (qe, msg, GNUNET_VECTORPRODUCT_Status_Success);
395 }
396 else if (ntohl (message->product_length) > 0)
397 {
398 // response for the requester client, successful
399 GNUNET_STATISTICS_update (h->stats,
400 gettext_noop ("# SUC requester result messages received"), 1,
401 GNUNET_NO);
402
403 LOG (GNUNET_ERROR_TYPE_DEBUG, "Received message from requester service for requester client.\n");
404 qe->response_proc (qe, msg, GNUNET_VECTORPRODUCT_Status_Success);
405 }
406
407 GNUNET_free (qe);
408 process_queue (h);
409}
410
411
412/**
413 * Transmits the request to the VectorProduct Sevice
414 *
415 * @param cls Closure
416 * @param size Size of the buffer
417 * @param buf Pointer to the buffer
418 *
419 * @return Size of the message sent
420 */
421static size_t
422transmit_request (void *cls, size_t size,
423 void *buf)
424{
425 struct GNUNET_VECTORPRODUCT_Handle *h = cls;
426 struct GNUNET_VECTORPRODUCT_QueueEntry *qe;
427 size_t msize;
428
429 if (NULL == (qe = h->queue_head))
430 {
431 LOG (GNUNET_ERROR_TYPE_DEBUG, "Queue head is NULL!\n\n");
432 return 0;
433 }
434
435 GNUNET_SCHEDULER_cancel (qe->timeout_task);
436 qe->timeout_task = GNUNET_SCHEDULER_NO_TASK;
437
438 h->th = NULL;
439 if (NULL == (qe = h->queue_head))
440 return 0; /* no entry in queue */
441 if (buf == NULL)
442 {
443 LOG (GNUNET_ERROR_TYPE_DEBUG, "Failed to transmit request to VECTORPRODUCT.\n");
444 GNUNET_STATISTICS_update (h->stats,
445 gettext_noop ("# transmission request failures"),
446 1, GNUNET_NO);
447 GNUNET_VECTORPRODUCT_disconnect (h);
448 return 0;
449 }
450 if (size < (msize = qe->message_size))
451 {
452 process_queue (h);
453 return 0;
454 }
455 LOG (GNUNET_ERROR_TYPE_DEBUG, "Transmitting %u byte request to VECTORPRODUCT\n",
456 msize);
457
458 memcpy (buf, qe->msg, size);
459 GNUNET_free (qe->msg);
460 qe->was_transmitted = GNUNET_YES;
461
462 GNUNET_assert (GNUNET_NO == h->in_receive);
463 h->in_receive = GNUNET_YES;
464
465 GNUNET_CLIENT_receive (h->client, &receive_cb, h,
466 GNUNET_TIME_UNIT_FOREVER_REL);
467
468#if INSANE_STATISTICS
469 GNUNET_STATISTICS_update (h->stats,
470 gettext_noop ("# bytes sent to vectorproduct"), 1,
471 GNUNET_NO);
472#endif
473 return size;
474}
475
476
477/**
478 * Issues transmit request for the new entries in the queue
479 *
480 * @param h handle to the master context
481 */
482static void
483process_queue (struct GNUNET_VECTORPRODUCT_Handle *h)
484{
485 struct GNUNET_VECTORPRODUCT_QueueEntry *qe;
486
487 if (NULL == (qe = h->queue_head))
488 {
489 LOG (GNUNET_ERROR_TYPE_DEBUG, "Queue empty\n");
490 return; /* no entry in queue */
491 }
492 if (qe->was_transmitted == GNUNET_YES)
493 {
494 LOG (GNUNET_ERROR_TYPE_DEBUG, "Head request already transmitted\n");
495 return; /* waiting for replies */
496 }
497 if (h->th != NULL)
498 {
499 LOG (GNUNET_ERROR_TYPE_DEBUG, "Pending transmission request\n");
500 return; /* request pending */
501 }
502 if (h->client == NULL)
503 {
504 LOG (GNUNET_ERROR_TYPE_DEBUG, "Not connected\n");
505 return; /* waiting for reconnect */
506 }
507 if (GNUNET_YES == h->in_receive)
508 {
509 /* wait for response to previous query */
510 return;
511 }
512
513 h->th =
514 GNUNET_CLIENT_notify_transmit_ready (h->client, qe->message_size,
515 GNUNET_TIME_UNIT_FOREVER_REL,
516 GNUNET_YES,
517 &transmit_request, h);
518
519 if (h->th == NULL)
520 {
521 LOG (GNUNET_ERROR_TYPE_ERROR,
522 _ ("Failed to send a message to the vectorproduct service\n"));
523 return;
524 }
525
526 GNUNET_assert (GNUNET_NO == h->in_receive);
527 GNUNET_break (NULL != h->th);
528}
529
530
531
532/**************************************************************
533 *** API **********
534 **************************************************************/
535
536
537/**
538 * Called by the responder client to prepare response
539 *
540 * @param h handle to the master context
541 * @param key Session key - unique to the requesting client
542 * @param element_count Number of elements in the vector
543 * @param mask_length number of bytes in the mask
544 * @param elements Array of elements of the vector
545 * @param mask Array of the mask
546 * @param timeout Relative timeout for the operation
547 * @param cont Callback function
548 * @param cont_cls Closure for the callback function
549 */
550struct GNUNET_VECTORPRODUCT_QueueEntry *
551GNUNET_VECTORPRODUCT_prepare_response (struct GNUNET_VECTORPRODUCT_Handle *h,
552 const struct GNUNET_HashCode * key,
553 uint16_t element_count,
554 int32_t * elements,
555 struct GNUNET_TIME_Relative timeout,
556 GNUNET_VECTORPRODUCT_ContinuationWithStatus cont,
557 void *cont_cls)
558{
559 struct GNUNET_VECTORPRODUCT_QueueEntry *qe = make_queue_entry (h);
560 int32_t * vector;
561 uint16_t size;
562 unsigned int i;
563
564 GNUNET_assert (GNUNET_SERVER_MAX_MESSAGE_SIZE >= sizeof (struct GNUNET_VECTORPRODUCT_client_request)
565 +element_count * sizeof (int32_t));
566 size = sizeof (struct GNUNET_VECTORPRODUCT_client_request) +element_count * sizeof (int32_t);
567
568 qe->message_size = size;
569 qe->msg = GNUNET_malloc (size);
570 qe->msg->header.size = htons (size);
571 qe->msg->header.type = htons (GNUNET_MESSAGE_TYPE_VECTORPRODUCT_CLIENT_TO_BOB);
572 qe->msg->element_count = htons (element_count);
573 qe->msg->mask_length = htons (0);
574 memcpy (&qe->msg->key, key, sizeof (struct GNUNET_HashCode));
575 qe->cont_status = cont;
576 qe->cont_cls = cont_cls;
577 qe->was_transmitted = GNUNET_NO;
578 qe->timeout_task = GNUNET_SCHEDULER_add_delayed (timeout, &timeout_queue_entry, qe);
579 qe->response_proc = &process_status_message;
580 qe->timeout = GNUNET_TIME_relative_to_absolute (timeout);
581
582 vector = (int32_t *) & qe->msg[1];
583 // copy each element over to the message
584 for (i = 0; i < element_count; i++)
585 vector[i] = htonl (elements[i]);
586
587 process_queue (h);
588 return qe;
589}
590
591
592/**
593 * Request the Scalar Product Evaluation
594 *
595 * @param h handle to the master context
596 * @param key Session key - unique to the requesting client
597 * @param peer PeerID of the other peer
598 * @param element_count Number of elements in the vector
599 * @param mask_length number of bytes in the mask
600 * @param elements Array of elements of the vector
601 * @param mask Array of the mask
602 * @param timeout Relative timeout for the operation
603 * @param cont Callback function
604 * @param cont_cls Closure for the callback function
605 */
606struct GNUNET_VECTORPRODUCT_QueueEntry *
607GNUNET_VECTORPRODUCT_request (struct GNUNET_VECTORPRODUCT_Handle *h,
608 const struct GNUNET_HashCode * key,
609 const struct GNUNET_PeerIdentity * peer,
610 uint16_t element_count,
611 uint16_t mask_length,
612 int32_t * elements,
613 const unsigned char * mask,
614 struct GNUNET_TIME_Relative timeout,
615 GNUNET_VECTORPRODUCT_DatumProcessor cont,
616 void *cont_cls)
617{
618 struct GNUNET_VECTORPRODUCT_QueueEntry *qe = make_queue_entry (h);
619 int32_t * vector;
620 uint16_t size;
621 unsigned int i;
622
623 GNUNET_assert (GNUNET_SERVER_MAX_MESSAGE_SIZE >= sizeof (struct GNUNET_VECTORPRODUCT_client_request)
624 +element_count * sizeof (int32_t)
625 + mask_length);
626 size = sizeof (struct GNUNET_VECTORPRODUCT_client_request) +element_count * sizeof (int32_t) + mask_length;
627
628 qe->message_size = size;
629 qe->msg = GNUNET_malloc (size);
630 qe->msg->header.size = htons (size);
631 qe->msg->header.type = htons (GNUNET_MESSAGE_TYPE_VECTORPRODUCT_CLIENT_TO_ALICE);
632 memcpy (&qe->msg->peer, peer, sizeof (struct GNUNET_PeerIdentity));
633 qe->msg->element_count = htons (element_count);
634 qe->msg->mask_length = htons (mask_length);
635 memcpy (&qe->msg->key, key, sizeof (struct GNUNET_HashCode));
636 qe->cont_datum = cont;
637 qe->cont_cls = cont_cls;
638 qe->was_transmitted = GNUNET_NO;
639 qe->timeout_task = GNUNET_SCHEDULER_add_delayed (timeout, &timeout_queue_entry, qe);
640 qe->response_proc = &process_result_message;
641 qe->timeout = GNUNET_TIME_relative_to_absolute (timeout);
642
643 vector = (int32_t*) & qe->msg[1];
644 // copy each element over to the message
645 for (i = 0; i < element_count; i++)
646 vector[i] = htonl (elements[i]);
647
648 // fill in the mask
649 memcpy (&vector[element_count], mask, mask_length);
650
651 process_queue (h);
652 return qe;
653}
654
655
656/**
657 * Connect to the vectorproduct service.
658 *
659 * @param cfg configuration to use
660 * @return handle to use to access the service
661 */
662struct GNUNET_VECTORPRODUCT_Handle *
663GNUNET_VECTORPRODUCT_connect (const struct GNUNET_CONFIGURATION_Handle * cfg)
664{
665 struct GNUNET_CLIENT_Connection *client;
666 struct GNUNET_VECTORPRODUCT_Handle *h;
667
668 client = GNUNET_CLIENT_connect ("vectorproduct", cfg);
669
670 if (NULL == client)
671 {
672 LOG (GNUNET_ERROR_TYPE_ERROR,
673 _ ("Failed to connect to the vectorproduct service\n"));
674 return NULL;
675 }
676
677 h = GNUNET_malloc (sizeof (struct GNUNET_VECTORPRODUCT_Handle) +
678 GNUNET_SERVER_MAX_MESSAGE_SIZE - 1);
679 h->client = client;
680 h->cfg = cfg;
681 h->stats = GNUNET_STATISTICS_create ("vectorproduct-api", cfg);
682 return h;
683}
684
685
686/**
687 * Disconnect from the vectorproduct service.
688 *
689 * @param h handle to the vectorproduct
690 */
691void
692GNUNET_VECTORPRODUCT_disconnect (struct GNUNET_VECTORPRODUCT_Handle * h)
693{
694 struct GNUNET_VECTORPRODUCT_QueueEntry * qe;
695
696 LOG (GNUNET_ERROR_TYPE_INFO,
697 "Disconnecting from VectorProduct\n");
698
699 while (NULL != h->queue_head)
700 {
701 GNUNET_assert (NULL != (qe = free_queue_head_entry (h)));
702 qe->response_proc (qe, NULL, GNUNET_VECTORPRODUCT_Status_ServiceDisconnected);
703 }
704
705 if (h->client != NULL)
706 {
707 GNUNET_CLIENT_disconnect (h->client);
708 h->client = NULL;
709 }
710
711 GNUNET_STATISTICS_destroy (h->stats, GNUNET_NO);
712 h->stats = NULL;
713}
714
715/* end of ext_api.c */