2 This file is part of GNUnet.
3 (C) 2009 Christian Grothoff (and other contributing authors)
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.
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.
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.
22 * @file core/core_api.c
23 * @brief core service; this is the main API for encrypted P2P
25 * @author Christian Grothoff
28 #include "gnunet_core_service.h"
33 * Context for the core service connection.
35 struct GNUNET_CORE_Handle
41 struct GNUNET_SCHEDULER_Handle *sched;
44 * Configuration we're using.
46 const struct GNUNET_CONFIGURATION_Handle *cfg;
49 * Closure for the various callbacks.
54 * Function to call once we've handshaked with the core service.
56 GNUNET_CORE_StartupCallback init;
59 * Function to call whenever we're notified about a peer connecting
60 * (pre-connects, no session key exchange yet).
62 GNUNET_CORE_ConnectEventHandler pre_connects;
65 * Function to call whenever we're notified about a peer connecting.
67 GNUNET_CORE_ConnectEventHandler connects;
70 * Function to call whenever we're notified about a peer disconnecting.
72 GNUNET_CORE_DisconnectEventHandler disconnects;
75 * Function to call whenever we receive an inbound message.
77 GNUNET_CORE_MessageCallback inbound_notify;
80 * Function to call whenever we receive an outbound message.
82 GNUNET_CORE_MessageCallback outbound_notify;
85 * Function handlers for messages of particular type.
87 const struct GNUNET_CORE_MessageHandler *handlers;
90 * Our connection to the service for notifications.
92 struct GNUNET_CLIENT_Connection *client_notifications;
95 * Handle for our current transmission request.
97 struct GNUNET_CLIENT_TransmitHandle *th;
100 * Head of doubly-linked list of pending requests.
102 struct GNUNET_CORE_TransmitHandle *pending_head;
105 * Tail of doubly-linked list of pending requests.
107 struct GNUNET_CORE_TransmitHandle *pending_tail;
110 * Currently submitted request (or NULL)
112 struct GNUNET_CORE_TransmitHandle *submitted;
115 * Currently submitted request based on solicitation (or NULL)
117 struct GNUNET_CORE_TransmitHandle *solicit_transmit_req;
120 * Buffer where we store a message for transmission in response
121 * to a traffic solicitation (or NULL).
123 char *solicit_buffer;
126 * How long to wait until we time out the connection attempt?
128 struct GNUNET_TIME_Absolute startup_timeout;
131 * ID of reconnect task (if any).
133 GNUNET_SCHEDULER_TaskIdentifier reconnect_task;
136 * Number of entries in the handlers array.
141 * For inbound notifications without a specific handler, do
142 * we expect to only receive headers?
144 int inbound_hdr_only;
147 * For outbound notifications without a specific handler, do
148 * we expect to only receive headers?
150 int outbound_hdr_only;
153 * Are we currently disconnected and hence unable to forward
161 * Handle for a transmission request.
163 struct GNUNET_CORE_TransmitHandle
167 * We keep active transmit handles in a doubly-linked list.
169 struct GNUNET_CORE_TransmitHandle *next;
172 * We keep active transmit handles in a doubly-linked list.
174 struct GNUNET_CORE_TransmitHandle *prev;
177 * Corresponding core handle.
179 struct GNUNET_CORE_Handle *ch;
182 * Function that will be called to get the actual request
183 * (once we are ready to transmit this request to the core).
184 * The function will be called with a NULL buffer to signal
187 GNUNET_CONNECTION_TransmitReadyNotify get_message;
190 * Closure for get_message.
192 void *get_message_cls;
195 * If this entry is for a transmission request, pointer
196 * to the notify callback; otherwise NULL.
198 GNUNET_CONNECTION_TransmitReadyNotify notify;
201 * Closure for notify.
206 * Peer the request is about.
208 struct GNUNET_PeerIdentity peer;
211 * Timeout for this handle.
213 struct GNUNET_TIME_Absolute timeout;
216 * ID of timeout task.
218 GNUNET_SCHEDULER_TaskIdentifier timeout_task;
221 * How important is this message?
226 * Size of this request.
235 * Function called when we are ready to transmit our
236 * "START" message (or when this operation timed out).
239 * @param size number of bytes available in buf
240 * @param buf where the callee should write the message
241 * @return number of bytes written to buf
243 static size_t transmit_start (void *cls, size_t size, void *buf);
247 * Our current client connection went down. Clean it up
248 * and try to reconnect!
250 * @param h our handle to the core service
253 reconnect (struct GNUNET_CORE_Handle *h)
255 GNUNET_CLIENT_disconnect (h->client_notifications);
256 h->currently_down = GNUNET_YES;
257 h->client_notifications = GNUNET_CLIENT_connect (h->sched, "core", h->cfg);
258 h->th = GNUNET_CLIENT_notify_transmit_ready (h->client_notifications,
259 sizeof (struct InitMessage) +
260 sizeof (uint16_t) * h->hcnt,
261 GNUNET_TIME_UNIT_SECONDS,
268 * The given request hit its timeout. Remove from the
269 * doubly-linked list and call the respective continuation.
271 * @param cls the transmit handle of the request that timed out
272 * @param tc context, can be NULL (!)
275 timeout_request (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
277 struct GNUNET_CORE_TransmitHandle *th = cls;
279 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
280 "Transmission request timed out.\n");
281 th->timeout_task = GNUNET_SCHEDULER_NO_TASK;
282 GNUNET_assert (0 == th->get_message (th->get_message_cls, 0, NULL));
287 * Function called when we are ready to transmit a request from our
288 * request list (or when this operation timed out).
291 * @param size number of bytes available in buf
292 * @param buf where the callee should write the message
293 * @return number of bytes written to buf
296 request_start (void *cls, size_t size, void *buf)
298 struct GNUNET_CORE_Handle *h = cls;
299 struct GNUNET_CORE_TransmitHandle *th;
302 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
303 "request_start called\n");
306 th = h->pending_head;
309 timeout_request (th, NULL);
312 /* create new timeout task (in case core takes too long to respond!) */
313 th->timeout_task = GNUNET_SCHEDULER_add_delayed (h->sched,
314 GNUNET_TIME_absolute_get_remaining
316 &timeout_request, th);
317 /* remove th from doubly-linked pending list, move to submitted */
318 GNUNET_assert (th->prev == NULL);
319 h->pending_head = th->next;
320 if (th->next == NULL)
321 h->pending_tail = NULL;
323 th->next->prev = NULL;
324 GNUNET_assert (h->submitted == NULL);
326 GNUNET_assert (size >= th->msize);
327 ret = th->get_message (th->get_message_cls, size, buf);
328 GNUNET_assert (ret <= size);
334 * Check the list of pending requests, send the next
338 trigger_next_request (struct GNUNET_CORE_Handle *h)
340 struct GNUNET_CORE_TransmitHandle *th;
342 if (h->currently_down)
344 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
345 "\nIn trigger_next_request, connection currently down...\n");
346 return; /* connection temporarily down */
348 if (NULL == (th = h->pending_head))
349 return; /* no requests pending */
350 GNUNET_assert (NULL == h->th);
351 if (GNUNET_SCHEDULER_NO_TASK != th->timeout_task)
353 GNUNET_SCHEDULER_cancel (h->sched, th->timeout_task);
354 th->timeout_task = GNUNET_SCHEDULER_NO_TASK;
356 h->th = GNUNET_CLIENT_notify_transmit_ready (h->client_notifications,
358 GNUNET_TIME_absolute_get_remaining
367 * Handler for notification messages received from the core.
369 * @param cls our "struct GNUNET_CORE_Handle"
370 * @param msg the message received from the core service
373 main_notify_handler (void *cls, const struct GNUNET_MessageHeader *msg)
375 struct GNUNET_CORE_Handle *h = cls;
377 const struct ConnectNotifyMessage *cnm;
378 const struct DisconnectNotifyMessage *dnm;
379 const struct NotifyTrafficMessage *ntm;
380 const struct GNUNET_MessageHeader *em;
383 const struct GNUNET_CORE_MessageHandler *mh;
387 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
389 ("Client was disconnected from core service, trying to reconnect.\n"));
393 msize = ntohs (msg->size);
395 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
396 "Processing message of type %u and size %u from core service\n",
397 ntohs (msg->type), msize);
399 switch (ntohs (msg->type))
401 case GNUNET_MESSAGE_TYPE_CORE_NOTIFY_PRE_CONNECT:
402 if (NULL == h->pre_connects)
407 if (msize != sizeof (struct ConnectNotifyMessage))
412 cnm = (const struct ConnectNotifyMessage *) msg;
413 h->pre_connects (h->cls,
415 GNUNET_TIME_relative_ntoh (cnm->latency),
416 ntohl (cnm->distance));
418 case GNUNET_MESSAGE_TYPE_CORE_NOTIFY_CONNECT:
419 if (NULL == h->connects)
424 if (msize != sizeof (struct ConnectNotifyMessage))
429 cnm = (const struct ConnectNotifyMessage *) msg;
432 GNUNET_TIME_relative_ntoh (cnm->latency),
433 ntohl (cnm->distance));
435 case GNUNET_MESSAGE_TYPE_CORE_NOTIFY_DISCONNECT:
436 if (NULL == h->disconnects)
441 if (msize != sizeof (struct DisconnectNotifyMessage))
446 dnm = (const struct DisconnectNotifyMessage *) msg;
447 h->disconnects (h->cls,
450 case GNUNET_MESSAGE_TYPE_CORE_NOTIFY_INBOUND:
452 sizeof (struct NotifyTrafficMessage) +
453 sizeof (struct GNUNET_MessageHeader))
458 ntm = (const struct NotifyTrafficMessage *) msg;
459 em = (const struct GNUNET_MessageHeader *) &ntm[1];
461 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
462 "Received message of type %u from peer `%4s'\n",
463 ntohs (em->type), GNUNET_i2s (&ntm->peer));
465 if ((GNUNET_NO == h->inbound_hdr_only) &&
466 (msize != ntohs (em->size) + sizeof (struct NotifyTrafficMessage)))
471 et = ntohs (em->type);
472 for (hpos = 0; hpos < h->hcnt; hpos++)
474 mh = &h->handlers[hpos];
477 if ((mh->expected_size != ntohs (em->size)) &&
478 (mh->expected_size != 0))
484 h->handlers[hpos].callback (h->cls, &ntm->peer, em,
485 GNUNET_TIME_relative_ntoh (ntm->latency),
486 ntohl (ntm->distance)))
488 /* error in processing, disconnect ! */
493 if (NULL != h->inbound_notify)
494 h->inbound_notify (h->cls, &ntm->peer, em,
495 GNUNET_TIME_relative_ntoh (ntm->latency),
496 ntohl (ntm->distance));
498 case GNUNET_MESSAGE_TYPE_CORE_NOTIFY_OUTBOUND:
500 sizeof (struct NotifyTrafficMessage) +
501 sizeof (struct GNUNET_MessageHeader))
506 ntm = (const struct NotifyTrafficMessage *) msg;
507 em = (const struct GNUNET_MessageHeader *) &ntm[1];
508 if ((GNUNET_NO == h->outbound_hdr_only) &&
509 (msize != ntohs (em->size) + sizeof (struct NotifyTrafficMessage)))
514 if (NULL == h->outbound_notify)
519 h->outbound_notify (h->cls, &ntm->peer, em,
520 GNUNET_TIME_relative_ntoh (ntm->latency),
521 ntohl (ntm->distance));
527 GNUNET_CLIENT_receive (h->client_notifications,
528 &main_notify_handler, h, GNUNET_TIME_UNIT_FOREVER_REL);
533 * Function called when we are ready to transmit our
534 * "START" message (or when this operation timed out).
537 * @param size number of bytes available in buf
538 * @param buf where the callee should write the message
539 * @return number of bytes written to buf
541 static size_t transmit_start (void *cls, size_t size, void *buf);
545 * Function called on the first message received from
546 * the service (contains our public key, etc.).
547 * Should trigger calling the init callback
548 * and then start our regular message processing.
551 * @param msg message received, NULL on timeout or fatal error
554 init_reply_handler (void *cls, const struct GNUNET_MessageHeader *msg)
556 struct GNUNET_CORE_Handle *h = cls;
557 const struct InitReplyMessage *m;
558 GNUNET_CORE_StartupCallback init;
559 struct GNUNET_PeerIdentity my_identity;
562 (ntohs (msg->size) != sizeof (struct InitReplyMessage)) ||
563 (ntohs (msg->type) != GNUNET_MESSAGE_TYPE_CORE_INIT_REPLY))
565 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
567 ("Error connecting to core service (failed to receive `%s' message).\n"),
569 GNUNET_break (msg == NULL);
570 transmit_start (h, 0, NULL);
573 m = (const struct InitReplyMessage *) msg;
574 /* start our message processing loop */
576 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
578 ("Successfully connected to core service, starting processing loop.\n"));
580 h->currently_down = GNUNET_NO;
581 trigger_next_request (h);
582 GNUNET_CLIENT_receive (h->client_notifications,
583 &main_notify_handler, h, GNUNET_TIME_UNIT_FOREVER_REL);
584 if (NULL != (init = h->init))
586 /* mark so we don't call init on reconnect */
589 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
590 _("Successfully connected to core service.\n"));
592 GNUNET_CRYPTO_hash (&m->publicKey,
594 GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded),
595 &my_identity.hashPubKey);
596 init (h->cls, h, &my_identity, &m->publicKey);
602 reconnect_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
604 struct GNUNET_CORE_Handle *h = cls;
605 h->reconnect_task = GNUNET_SCHEDULER_NO_TASK;
611 * Function called when we are ready to transmit our
612 * "START" message (or when this operation timed out).
615 * @param size number of bytes available in buf
616 * @param buf where the callee should write the message
617 * @return number of bytes written to buf
620 transmit_start (void *cls, size_t size, void *buf)
622 struct GNUNET_CORE_Handle *h = cls;
623 struct InitMessage *init;
628 struct GNUNET_TIME_Relative delay;
633 if ((h->init == NULL) ||
634 (GNUNET_TIME_absolute_get ().value < h->startup_timeout.value))
636 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
637 _("Failed to connect to core service, retrying.\n"));
638 delay = GNUNET_TIME_absolute_get_remaining (h->startup_timeout);
639 if ((h->init == NULL) || (delay.value > 1000))
640 delay = GNUNET_TIME_UNIT_SECONDS;
643 GNUNET_TIME_relative_to_absolute (GNUNET_TIME_UNIT_MINUTES);
645 GNUNET_SCHEDULER_add_delayed (h->sched,
646 delay, &reconnect_task, h);
649 /* timeout on initial connect */
650 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
651 _("Failed to connect to core service, giving up.\n"));
652 h->init (h->cls, NULL, NULL, NULL);
653 GNUNET_CORE_disconnect (h);
656 msize = h->hcnt * sizeof (uint16_t) + sizeof (struct InitMessage);
657 GNUNET_assert (size >= msize);
659 init->header.type = htons (GNUNET_MESSAGE_TYPE_CORE_INIT);
660 init->header.size = htons (msize);
661 opt = GNUNET_CORE_OPTION_NOTHING;
662 if (h->pre_connects != NULL)
663 opt |= GNUNET_CORE_OPTION_SEND_PRE_CONNECT;
664 if (h->connects != NULL)
665 opt |= GNUNET_CORE_OPTION_SEND_CONNECT;
666 if (h->disconnects != NULL)
667 opt |= GNUNET_CORE_OPTION_SEND_DISCONNECT;
668 if (h->inbound_notify != NULL)
670 if (h->inbound_hdr_only)
671 opt |= GNUNET_CORE_OPTION_SEND_HDR_INBOUND;
673 opt |= GNUNET_CORE_OPTION_SEND_FULL_INBOUND;
675 if (h->outbound_notify != NULL)
677 if (h->outbound_hdr_only)
678 opt |= GNUNET_CORE_OPTION_SEND_HDR_OUTBOUND;
680 opt |= GNUNET_CORE_OPTION_SEND_FULL_OUTBOUND;
682 init->options = htonl (opt);
683 ts = (uint16_t *) & init[1];
684 for (hpos = 0; hpos < h->hcnt; hpos++)
685 ts[hpos] = htons (h->handlers[hpos].type);
686 GNUNET_CLIENT_receive (h->client_notifications,
689 GNUNET_TIME_absolute_get_remaining
690 (h->startup_timeout));
691 return sizeof (struct InitMessage) + h->hcnt * sizeof (uint16_t);
696 * Connect to the core service. Note that the connection may
697 * complete (or fail) asynchronously.
699 * @param sched scheduler to use
700 * @param cfg configuration to use
701 * @param timeout after how long should we give up trying to connect to the core service?
702 * @param cls closure for the various callbacks that follow (including handlers in the handlers array)
703 * @param init callback to call on timeout or once we have successfully
704 * connected to the core service; note that timeout is only meaningful if init is not NULL
705 * @param pre_connects function to call on peer pre-connect (no session key yet), can be NULL
706 * @param connects function to call on peer connect, can be NULL
707 * @param disconnects function to call on peer disconnect / timeout, can be NULL
708 * @param inbound_notify function to call for all inbound messages, can be NULL
709 * @param inbound_hdr_only set to GNUNET_YES if inbound_notify will only read the
710 * GNUNET_MessageHeader and hence we do not need to give it the full message;
711 * can be used to improve efficiency, ignored if inbound_notify is NULLL
712 * @param outbound_notify function to call for all outbound messages, can be NULL
713 * @param outbound_hdr_only set to GNUNET_YES if outbound_notify will only read the
714 * GNUNET_MessageHeader and hence we do not need to give it the full message
715 * can be used to improve efficiency, ignored if outbound_notify is NULLL
716 * @param handlers callbacks for messages we care about, NULL-terminated
717 * @return handle to the core service (only useful for disconnect until 'init' is called);
718 * NULL on error (in this case, init is never called)
720 struct GNUNET_CORE_Handle *
721 GNUNET_CORE_connect (struct GNUNET_SCHEDULER_Handle *sched,
722 const struct GNUNET_CONFIGURATION_Handle *cfg,
723 struct GNUNET_TIME_Relative timeout,
725 GNUNET_CORE_StartupCallback init,
726 GNUNET_CORE_ConnectEventHandler pre_connects,
727 GNUNET_CORE_ConnectEventHandler connects,
728 GNUNET_CORE_DisconnectEventHandler disconnects,
729 GNUNET_CORE_MessageCallback inbound_notify,
730 int inbound_hdr_only,
731 GNUNET_CORE_MessageCallback outbound_notify,
732 int outbound_hdr_only,
733 const struct GNUNET_CORE_MessageHandler *handlers)
735 struct GNUNET_CORE_Handle *h;
737 h = GNUNET_malloc (sizeof (struct GNUNET_CORE_Handle));
742 h->pre_connects = pre_connects;
743 h->connects = connects;
744 h->disconnects = disconnects;
745 h->inbound_notify = inbound_notify;
746 h->outbound_notify = outbound_notify;
747 h->inbound_hdr_only = inbound_hdr_only;
748 h->outbound_hdr_only = outbound_hdr_only;
749 h->handlers = handlers;
750 h->client_notifications = GNUNET_CLIENT_connect (sched, "core", cfg);
751 if (h->client_notifications == NULL)
756 h->startup_timeout = GNUNET_TIME_relative_to_absolute (timeout);
758 while (handlers[h->hcnt].callback != NULL)
760 GNUNET_assert (h->hcnt <
761 (GNUNET_SERVER_MAX_MESSAGE_SIZE -
762 sizeof (struct InitMessage)) / sizeof (uint16_t));
764 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
765 "Trying to connect to core service in next %llu ms.\n",
769 GNUNET_CLIENT_notify_transmit_ready (h->client_notifications,
770 sizeof (struct InitMessage) +
771 sizeof (uint16_t) * h->hcnt, timeout,
779 * Disconnect from the core service.
781 * @param handle connection to core to disconnect
784 GNUNET_CORE_disconnect (struct GNUNET_CORE_Handle *handle)
786 if (handle->th != NULL)
787 GNUNET_CLIENT_notify_transmit_ready_cancel (handle->th);
788 if (handle->solicit_transmit_req != NULL)
789 GNUNET_CORE_notify_transmit_ready_cancel (handle->solicit_transmit_req);
790 if (handle->reconnect_task != GNUNET_SCHEDULER_NO_TASK)
791 GNUNET_SCHEDULER_cancel (handle->sched, handle->reconnect_task);
792 GNUNET_CLIENT_disconnect (handle->client_notifications);
793 GNUNET_free_non_null (handle->solicit_buffer);
794 GNUNET_free (handle);
799 * Build the message requesting data transmission.
802 produce_send (void *cls, size_t size, void *buf)
804 struct GNUNET_CORE_TransmitHandle *th = cls;
805 struct GNUNET_CORE_Handle *h;
806 struct SendMessage *sm;
808 GNUNET_CONNECTION_TransmitReadyNotify notify;
814 /* timeout or error */
816 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
817 "P2P transmission request for `%4s' timed out.\n",
818 GNUNET_i2s(&th->peer));
820 GNUNET_assert (0 == th->notify (th->notify_cls, 0, NULL));
821 GNUNET_CORE_notify_transmit_ready_cancel (th);
822 trigger_next_request (h);
826 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
827 "Preparing for P2P transmission to `%4s'.\n",
828 GNUNET_i2s(&th->peer));
830 GNUNET_assert (th->timeout_task != GNUNET_SCHEDULER_NO_TASK);
831 sm = (struct SendMessage *) buf;
832 sm->header.type = htons (GNUNET_MESSAGE_TYPE_CORE_SEND);
833 sm->priority = htonl (th->priority);
834 sm->deadline = GNUNET_TIME_absolute_hton (th->timeout);
837 notify_cls = th->notify_cls;
838 GNUNET_CORE_notify_transmit_ready_cancel (th);
839 trigger_next_request (h);
840 GNUNET_assert (size >= sizeof (struct SendMessage));
841 dt = notify (notify_cls, size - sizeof (struct SendMessage), &sm[1]);
845 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
846 "Size of clients message to peer %s is 0!\n",
847 GNUNET_i2s(&th->peer));
849 /* client decided to send nothing! */
852 GNUNET_assert (dt >= sizeof (struct GNUNET_MessageHeader));
853 sm->header.size = htons (dt + sizeof (struct SendMessage));
854 GNUNET_assert (dt + sizeof (struct SendMessage) <= size);
855 return dt + sizeof (struct SendMessage);
860 * Ask the core to call "notify" once it is ready to transmit the
861 * given number of bytes to the specified "target". If we are not yet
862 * connected to the specified peer, a call to this function will cause
863 * us to try to establish a connection.
865 * @param handle connection to core service
866 * @param priority how important is the message?
867 * @param maxdelay how long can the message wait?
868 * @param target who should receive the message,
869 * use NULL for this peer (loopback)
870 * @param notify_size how many bytes of buffer space does notify want?
871 * @param notify function to call when buffer space is available
872 * @param notify_cls closure for notify
873 * @return non-NULL if the notify callback was queued,
874 * NULL if we can not even queue the request (insufficient
875 * memory); if NULL is returned, "notify" will NOT be called.
877 struct GNUNET_CORE_TransmitHandle *
878 GNUNET_CORE_notify_transmit_ready (struct GNUNET_CORE_Handle *handle,
879 unsigned int priority,
880 struct GNUNET_TIME_Relative maxdelay,
881 const struct GNUNET_PeerIdentity *target,
883 GNUNET_CONNECTION_TransmitReadyNotify notify,
886 struct GNUNET_CORE_TransmitHandle *th;
888 GNUNET_assert (notify_size + sizeof (struct SendMessage) <
889 GNUNET_SERVER_MAX_MESSAGE_SIZE);
890 th = GNUNET_malloc (sizeof (struct GNUNET_CORE_TransmitHandle));
893 th->prev = handle->pending_tail;
894 if (handle->pending_tail == NULL)
895 handle->pending_head = th;
897 handle->pending_tail->next = th;
898 th->get_message = &produce_send;
899 th->get_message_cls = th;
901 th->notify_cls = notify_cls;
903 th->timeout = GNUNET_TIME_relative_to_absolute (maxdelay);
904 th->timeout_task = GNUNET_SCHEDULER_add_delayed (handle->sched,
906 &timeout_request, th);
907 th->priority = priority;
908 th->msize = sizeof (struct SendMessage) + notify_size;
909 /* was the request queue previously empty? */
910 if ( (handle->pending_head == th) &&
911 (handle->th == NULL) )
912 trigger_next_request (handle);
918 * Cancel the specified transmission-ready notification.
920 * @param h handle that was returned by "notify_transmit_ready".
923 GNUNET_CORE_notify_transmit_ready_cancel (struct GNUNET_CORE_TransmitHandle
926 struct GNUNET_CORE_Handle *handle = h->ch;
928 if (handle->submitted == h)
930 handle->submitted = NULL;
935 handle->pending_head = h->next;
937 h->prev->next = h->next;
939 handle->pending_tail = h->prev;
941 h->next->prev = h->prev;
943 if (h->timeout_task != GNUNET_SCHEDULER_NO_TASK)
944 GNUNET_SCHEDULER_cancel (handle->sched, h->timeout_task);
949 /* end of core_api.c */