X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=src%2Fcore%2Fcore_api.c;h=30b7eb5405ee7ce427e22f74905be57afdfbd87f;hb=81825d24a7088d8bf3c4b8ac8685403836c53eae;hp=7d3e3d41d4c9000a3d1c2333bef455425bb3d2eb;hpb=47f65a4ce8fb23800a1a1093bc0b14038b3dc20b;p=oweals%2Fgnunet.git diff --git a/src/core/core_api.c b/src/core/core_api.c index 7d3e3d41d..30b7eb540 100644 --- a/src/core/core_api.c +++ b/src/core/core_api.c @@ -129,12 +129,10 @@ struct ControlMessage struct ControlMessage *prev; /** - * Function to run after successful transmission (or call with - * reason 'TIMEOUT' on error); called with scheduler context 'NULL' - * on disconnect. + * Function to run after transmission failed/succeeded. */ - GNUNET_SCHEDULER_Task cont; - + GNUNET_CORE_ControlContinuation cont; + /** * Closure for 'cont'. */ @@ -212,12 +210,12 @@ struct GNUNET_CORE_Handle /** * Head of doubly-linked list of pending requests. */ - struct ControlMessage *pending_head; + struct ControlMessage *control_pending_head; /** * Tail of doubly-linked list of pending requests. */ - struct ControlMessage *pending_tail; + struct ControlMessage *control_pending_tail; /** * Head of doubly-linked list of peers that are core-approved @@ -348,6 +346,11 @@ struct GNUNET_CORE_TransmitHandle */ uint16_t smr_id; + /** + * Is corking allowed? + */ + int cork; + }; @@ -419,7 +422,9 @@ disconnect_and_free_peer_entry (void *cls, pcic (pr->pcic_cls, &pr->peer, zero, - 0, 0); + 0, + GNUNET_TIME_UNIT_FOREVER_REL, + 0); } if (pr->timeout_task != GNUNET_SCHEDULER_NO_TASK) { @@ -462,17 +467,7 @@ reconnect_later (struct GNUNET_CORE_Handle *h) struct ControlMessage *cm; struct PeerRecord *pr; - while (NULL != (cm = h->pending_head)) - { - GNUNET_CONTAINER_DLL_remove (h->pending_head, - h->pending_tail, - cm); - if (cm->th != NULL) - cm->th->cm = NULL; - if (cm->cont != NULL) - cm->cont (cm->cont_cls, NULL); - GNUNET_free (cm); - } + GNUNET_assert (h->reconnect_task == GNUNET_SCHEDULER_NO_TASK); if (h->client != NULL) { GNUNET_CLIENT_disconnect (h->client, GNUNET_NO); @@ -486,15 +481,24 @@ reconnect_later (struct GNUNET_CORE_Handle *h) GNUNET_CONTAINER_DLL_remove (h->ready_peer_head, h->ready_peer_tail, pr); - - GNUNET_assert (h->pending_head == NULL); h->currently_down = GNUNET_YES; - GNUNET_assert (h->reconnect_task == GNUNET_SCHEDULER_NO_TASK); - h->retry_backoff = GNUNET_TIME_relative_min (GNUNET_TIME_UNIT_SECONDS, - h->retry_backoff); h->reconnect_task = GNUNET_SCHEDULER_add_delayed (h->retry_backoff, &reconnect_task, h); + while (NULL != (cm = h->control_pending_head)) + { + GNUNET_CONTAINER_DLL_remove (h->control_pending_head, + h->control_pending_tail, + cm); + if (cm->th != NULL) + cm->th->cm = NULL; + if (cm->cont != NULL) + cm->cont (cm->cont_cls, GNUNET_NO); + GNUNET_free (cm); + } + GNUNET_assert (h->control_pending_head == NULL); + h->retry_backoff = GNUNET_TIME_relative_min (GNUNET_TIME_UNIT_SECONDS, + h->retry_backoff); h->retry_backoff = GNUNET_TIME_relative_multiply (h->retry_backoff, 2); } @@ -547,6 +551,8 @@ request_next_transmission (struct PeerRecord *pr) trigger_next_request (h, GNUNET_NO); return; } + if (th->cm != NULL) + return; /* already done */ GNUNET_assert (pr->prev == NULL); GNUNET_assert (pr->next == NULL); pr->timeout_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_absolute_get_remaining (th->timeout), @@ -565,9 +571,9 @@ request_next_transmission (struct PeerRecord *pr) smr->queue_size = htonl (pr->queue_size); smr->size = htons (th->msize); smr->smr_id = htons (th->smr_id = pr->smr_id_gen++); - GNUNET_CONTAINER_DLL_insert_after (h->pending_head, - h->pending_tail, - h->pending_tail, + GNUNET_CONTAINER_DLL_insert_after (h->control_pending_head, + h->control_pending_tail, + h->control_pending_tail, cm); #if DEBUG_CORE GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, @@ -636,6 +642,7 @@ transmit_message (void *cls, uint16_t msize; size_t ret; + GNUNET_assert (h->reconnect_task == GNUNET_SCHEDULER_NO_TASK); h->cth = NULL; if (buf == NULL) { @@ -647,7 +654,7 @@ transmit_message (void *cls, return 0; } /* first check for control messages */ - if (NULL != (cm = h->pending_head)) + if (NULL != (cm = h->control_pending_head)) { hdr = (const struct GNUNET_MessageHeader*) &cm[1]; msize = ntohs (hdr->size); @@ -663,15 +670,13 @@ transmit_message (void *cls, (unsigned int) ntohs (hdr->type)); #endif memcpy (buf, hdr, msize); - GNUNET_CONTAINER_DLL_remove (h->pending_head, - h->pending_tail, + GNUNET_CONTAINER_DLL_remove (h->control_pending_head, + h->control_pending_tail, cm); if (cm->th != NULL) cm->th->cm = NULL; if (NULL != cm->cont) - GNUNET_SCHEDULER_add_continuation (cm->cont, - cm->cont_cls, - GNUNET_SCHEDULER_REASON_PREREQ_DONE); + cm->cont (cm->cont_cls, GNUNET_OK); GNUNET_free (cm); trigger_next_request (h, GNUNET_NO); return msize; @@ -709,6 +714,8 @@ transmit_message (void *cls, sm->priority = htonl (th->priority); sm->deadline = GNUNET_TIME_absolute_hton (th->timeout); sm->peer = pr->peer; + sm->cork = htonl ((uint32_t) th->cork); + sm->reserved = htonl (0); ret = th->get_message (th->get_message_cls, size - sizeof (struct SendMessage), &sm[1]); @@ -777,8 +784,8 @@ trigger_next_request (struct GNUNET_CORE_Handle *h, #endif return; } - if (h->pending_head != NULL) - msize = ntohs (((struct GNUNET_MessageHeader*) &h->pending_head[1])->size); + if (h->control_pending_head != NULL) + msize = ntohs (((struct GNUNET_MessageHeader*) &h->control_pending_head[1])->size); else if (h->ready_peer_head != NULL) msize = h->ready_peer_head->pending_head->msize + sizeof (struct SendMessage); else @@ -923,7 +930,7 @@ main_notify_handler (void *cls, &cnm->peer, sizeof (struct GNUNET_PeerIdentity))) { - /* disconnect from self!? */ + /* connect to self!? */ GNUNET_break (0); return; } @@ -989,7 +996,6 @@ main_notify_handler (void *cls, if (NULL == h->status_events) { GNUNET_break (0); - break; } if (msize < sizeof (struct PeerStatusNotifyMessage)) { @@ -1042,14 +1048,7 @@ main_notify_handler (void *cls, return; } ntm = (const struct NotifyTrafficMessage *) msg; - if (0 == memcmp (&h->me, - &ntm->peer, - sizeof (struct GNUNET_PeerIdentity))) - { - /* self-change!? */ - GNUNET_break (0); - return; - } + ats_count = ntohl (ntm->ats_count); if ( (msize < sizeof (struct NotifyTrafficMessage) + ats_count * sizeof (struct GNUNET_TRANSPORT_ATS_Information) + sizeof (struct GNUNET_MessageHeader)) || @@ -1241,7 +1240,13 @@ main_notify_handler (void *cls, return; } if (pr->rim_id != ntohl (cim->rim_id)) - break; + { +#if DEBUG_CORE + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Reservation ID mismatch in notification...\n"); +#endif + break; + } pcic = pr->pcic; pr->pcic = NULL; if (pcic != NULL) @@ -1249,6 +1254,7 @@ main_notify_handler (void *cls, &pr->peer, cim->bw_out, ntohl (cim->reserved_amount), + GNUNET_TIME_relative_ntoh (cim->reserve_delay), GNUNET_ntohll (cim->preference)); break; default: @@ -1266,23 +1272,24 @@ main_notify_handler (void *cls, * Starts our 'receive' loop. * * @param cls the 'struct GNUNET_CORE_Handle' - * @param tc task context + * @param success were we successful */ static void init_done_task (void *cls, - const struct GNUNET_SCHEDULER_TaskContext *tc) + int success) { struct GNUNET_CORE_Handle *h = cls; - if (tc == NULL) - return; /* error */ - if (0 == (tc->reason & GNUNET_SCHEDULER_REASON_PREREQ_DONE)) + if (success == GNUNET_SYSERR) + return; /* shutdown */ + if (success == GNUNET_NO) { #if DEBUG_CORE GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Failed to exchange INIT with core, retrying\n"); #endif - reconnect_later (h); + if (h->reconnect_task == GNUNET_SCHEDULER_NO_TASK) + reconnect_later (h); return; } GNUNET_CLIENT_receive (h->client, @@ -1349,8 +1356,8 @@ reconnect (struct GNUNET_CORE_Handle *h) ts = (uint16_t *) &init[1]; for (hpos = 0; hpos < h->hcnt; hpos++) ts[hpos] = htons (h->handlers[hpos].type); - GNUNET_CONTAINER_DLL_insert (h->pending_head, - h->pending_tail, + GNUNET_CONTAINER_DLL_insert (h->control_pending_head, + h->control_pending_tail, cm); trigger_next_request (h, GNUNET_YES); } @@ -1454,22 +1461,22 @@ GNUNET_CORE_disconnect (struct GNUNET_CORE_Handle *handle) GNUNET_CLIENT_disconnect (handle->client, GNUNET_NO); handle->client = NULL; } - if (handle->reconnect_task != GNUNET_SCHEDULER_NO_TASK) - { - GNUNET_SCHEDULER_cancel (handle->reconnect_task); - handle->reconnect_task = GNUNET_SCHEDULER_NO_TASK; - } - while (NULL != (cm = handle->pending_head)) + while (NULL != (cm = handle->control_pending_head)) { - GNUNET_CONTAINER_DLL_remove (handle->pending_head, - handle->pending_tail, + GNUNET_CONTAINER_DLL_remove (handle->control_pending_head, + handle->control_pending_tail, cm); if (cm->th != NULL) cm->th->cm = NULL; if (cm->cont != NULL) - cm->cont (cm->cont_cls, NULL); + cm->cont (cm->cont_cls, GNUNET_SYSERR); GNUNET_free (cm); } + if (handle->reconnect_task != GNUNET_SCHEDULER_NO_TASK) + { + GNUNET_SCHEDULER_cancel (handle->reconnect_task); + handle->reconnect_task = GNUNET_SCHEDULER_NO_TASK; + } GNUNET_CONTAINER_multihashmap_iterate (handle->peers, &disconnect_and_free_peer_entry, handle); @@ -1481,11 +1488,12 @@ GNUNET_CORE_disconnect (struct GNUNET_CORE_Handle *handle) /** * Ask the core to call "notify" once it is ready to transmit the - * given number of bytes to the specified "target". If we are not yet - * connected to the specified peer, a call to this function will cause - * us to try to establish a connection. + * given number of bytes to the specified "target". Must only be + * called after a connection to the respective peer has been + * established (and the client has been informed about this). * * @param handle connection to core service + * @param cork is corking allowed for this transmission? * @param priority how important is the message? * @param maxdelay how long can the message wait? * @param target who should receive the message, @@ -1499,6 +1507,7 @@ GNUNET_CORE_disconnect (struct GNUNET_CORE_Handle *handle) */ struct GNUNET_CORE_TransmitHandle * GNUNET_CORE_notify_transmit_ready (struct GNUNET_CORE_Handle *handle, + int cork, uint32_t priority, struct GNUNET_TIME_Relative maxdelay, const struct GNUNET_PeerIdentity *target, @@ -1527,11 +1536,13 @@ GNUNET_CORE_notify_transmit_ready (struct GNUNET_CORE_Handle *handle, GNUNET_SERVER_MAX_MESSAGE_SIZE); th = GNUNET_malloc (sizeof (struct GNUNET_CORE_TransmitHandle)); th->peer = pr; + GNUNET_assert(NULL != notify); th->get_message = notify; th->get_message_cls = notify_cls; th->timeout = GNUNET_TIME_relative_to_absolute (maxdelay); th->priority = priority; th->msize = notify_size; + th->cork = cork; /* bound queue size */ if (pr->queue_size == handle->queue_size) { @@ -1547,7 +1558,7 @@ GNUNET_CORE_notify_transmit_ready (struct GNUNET_CORE_Handle *handle, if (minp == NULL) { GNUNET_break (handle->queue_size != 0); - GNUNET_break (pr->queue_size == 0); + GNUNET_break (pr->queue_size == 1); GNUNET_free(th); return NULL; } @@ -1625,8 +1636,8 @@ GNUNET_CORE_notify_transmit_ready_cancel (struct GNUNET_CORE_TransmitHandle if (th->cm != NULL) { /* we're currently in the control queue, remove */ - GNUNET_CONTAINER_DLL_remove (h->pending_head, - h->pending_tail, + GNUNET_CONTAINER_DLL_remove (h->control_pending_head, + h->control_pending_tail, th->cm); GNUNET_free (th->cm); } @@ -1672,7 +1683,7 @@ struct GNUNET_CORE_PeerRequestHandle /** * Continuation to run when done. */ - GNUNET_SCHEDULER_Task cont; + GNUNET_CORE_ControlContinuation cont; /** * Closure for 'cont'. @@ -1688,22 +1699,16 @@ struct GNUNET_CORE_PeerRequestHandle * resources. * * @param cls the 'struct GNUNET_CORE_PeerRequestHandle' - * @param tc scheduler context + * @param success was the request transmitted? */ static void peer_request_connect_cont (void *cls, - const struct GNUNET_SCHEDULER_TaskContext *tc) + int success) { struct GNUNET_CORE_PeerRequestHandle *ret = cls; if (ret->cont != NULL) - { - if (tc == NULL) - GNUNET_SCHEDULER_add_now (ret->cont, - ret->cont_cls); - else - ret->cont (ret->cont_cls, tc); - } + ret->cont (ret->cont_cls, success); GNUNET_free (ret); } @@ -1724,18 +1729,29 @@ peer_request_connect_cont (void *cls, * @param peer who should we connect to * @param cont function to call once the request has been completed (or timed out) * @param cont_cls closure for cont - * @return NULL on error (cont will not be called), otherwise handle for cancellation + * + * @return NULL on error or already connected, + * otherwise handle for cancellation */ struct GNUNET_CORE_PeerRequestHandle * GNUNET_CORE_peer_request_connect (struct GNUNET_CORE_Handle *h, struct GNUNET_TIME_Relative timeout, const struct GNUNET_PeerIdentity * peer, - GNUNET_SCHEDULER_Task cont, + GNUNET_CORE_ControlContinuation cont, void *cont_cls) { struct GNUNET_CORE_PeerRequestHandle *ret; struct ControlMessage *cm; struct ConnectMessage *msg; + + if (NULL != GNUNET_CONTAINER_multihashmap_get (h->peers, + &peer->hashPubKey)) + { +#if DEBUG_CORE + GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Peers are already connected!\n"); +#endif + return NULL; + } cm = GNUNET_malloc (sizeof (struct ControlMessage) + sizeof (struct ConnectMessage)); @@ -1745,9 +1761,9 @@ GNUNET_CORE_peer_request_connect (struct GNUNET_CORE_Handle *h, msg->reserved = htonl (0); msg->timeout = GNUNET_TIME_relative_hton (timeout); msg->peer = *peer; - GNUNET_CONTAINER_DLL_insert (h->pending_head, - h->pending_tail, - cm); + GNUNET_CONTAINER_DLL_insert_tail (h->control_pending_head, + h->control_pending_tail, + cm); ret = GNUNET_malloc (sizeof (struct GNUNET_CORE_PeerRequestHandle)); ret->h = h; ret->cm = cm; @@ -1759,7 +1775,7 @@ GNUNET_CORE_peer_request_connect (struct GNUNET_CORE_Handle *h, GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Queueing REQUEST_CONNECT request\n"); #endif - if (h->pending_head == cm) + if (h->control_pending_head == cm) trigger_next_request (h, GNUNET_NO); return ret; } @@ -1777,8 +1793,8 @@ GNUNET_CORE_peer_request_connect_cancel (struct GNUNET_CORE_PeerRequestHandle *r struct GNUNET_CORE_Handle *h = req->h; struct ControlMessage *cm = req->cm; - GNUNET_CONTAINER_DLL_remove (h->pending_head, - h->pending_tail, + GNUNET_CONTAINER_DLL_remove (h->control_pending_head, + h->control_pending_tail, cm); GNUNET_free (cm); GNUNET_free (req); @@ -1796,16 +1812,6 @@ struct GNUNET_CORE_InformationRequestContext */ struct GNUNET_CORE_Handle *h; - /** - * Function to call with the information. - */ - GNUNET_CORE_PeerConfigurationInfoCallback info; - - /** - * Closure for info. - */ - void *info_cls; - /** * Link to control message, NULL if CM was sent. */ @@ -1822,11 +1828,11 @@ struct GNUNET_CORE_InformationRequestContext * CM was sent, remove link so we don't double-free. * * @param cls the 'struct GNUNET_CORE_InformationRequestContext' - * @param tc scheduler context + * @param success were we successful? */ static void change_preference_send_continuation (void *cls, - const struct GNUNET_SCHEDULER_TaskContext *tc) + int success) { struct GNUNET_CORE_InformationRequestContext *irc = cls; @@ -1890,8 +1896,6 @@ GNUNET_CORE_peer_change_preference (struct GNUNET_CORE_Handle *h, irc = GNUNET_malloc (sizeof (struct GNUNET_CORE_InformationRequestContext)); irc->h = h; irc->pr = pr; - irc->info = info; - irc->info_cls = info_cls; cm = GNUNET_malloc (sizeof (struct ControlMessage) + sizeof (struct RequestInfoMessage)); cm->cont = &change_preference_send_continuation; @@ -1909,12 +1913,12 @@ GNUNET_CORE_peer_change_preference (struct GNUNET_CORE_Handle *h, GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Queueing CHANGE PREFERENCE request\n"); #endif - GNUNET_CONTAINER_DLL_insert (h->pending_head, - h->pending_tail, - cm); + GNUNET_CONTAINER_DLL_insert_tail (h->control_pending_head, + h->control_pending_tail, + cm); pr->pcic = info; pr->pcic_cls = info_cls; - if (h->pending_head == cm) + if (h->control_pending_head == cm) trigger_next_request (h, GNUNET_NO); return irc; } @@ -1939,8 +1943,8 @@ GNUNET_CORE_peer_change_preference_cancel (struct GNUNET_CORE_InformationRequest if (irc->cm != NULL) { - GNUNET_CONTAINER_DLL_remove (h->pending_head, - h->pending_tail, + GNUNET_CONTAINER_DLL_remove (h->control_pending_head, + h->control_pending_tail, irc->cm); GNUNET_free (irc->cm); }