From db6c313c75a36bc4a27971d7bd8da3e938c7c02a Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Sat, 13 Nov 2010 20:37:37 +0000 Subject: the big core API/protocol change, breaks all testcases using core, since the code is still buggy --- TODO | 7 + src/Makefile.am | 2 +- src/core/Makefile.am | 5 +- src/core/core.h | 143 +- src/core/core_api.c | 1539 +++++++++++++++----- src/core/core_api_iterate_peers.c | 169 --- src/core/core_api_peer_get_info.c | 175 --- src/core/core_api_peer_request.c | 179 --- src/core/gnunet-service-core.c | 364 ++++- src/core/test_core_api.c | 19 +- src/core/test_core_api_reliability.c | 14 +- src/core/test_core_api_start_only.c | 17 +- src/core/test_core_quota_compliance.c | 106 +- src/dht/gnunet-dht-driver.c | 6 - src/dht/gnunet-service-dht.c | 59 +- src/dv/Makefile.am | 2 +- src/dv/gnunet-service-dv.c | 76 +- src/fs/gnunet-service-fs.c | 57 +- src/hostlist/gnunet-daemon-hostlist.c | 20 +- src/hostlist/hostlist-client.c | 16 +- src/hostlist/hostlist-server.c | 6 +- .../test_gnunet_daemon_hostlist_learning.c | 11 +- src/include/gnunet_core_service.h | 78 +- src/include/gnunet_protocols.h | 19 +- src/include/gnunet_testing_lib.h | 2 - src/include/gnunet_transport_plugin.h | 335 ----- src/include/gnunet_transport_service.h | 338 +++++ src/testing/test_testing_topology.c | 7 +- src/testing/testing.c | 42 +- src/testing/testing_group.c | 14 +- src/topology/gnunet-daemon-topology.c | 15 +- 31 files changed, 2171 insertions(+), 1671 deletions(-) delete mode 100644 src/core/core_api_iterate_peers.c delete mode 100644 src/core/core_api_peer_get_info.c delete mode 100644 src/core/core_api_peer_request.c diff --git a/TODO b/TODO index e172e3b0d..9d9eccf97 100644 --- a/TODO +++ b/TODO @@ -1,4 +1,11 @@ 0.9.0pre2: +* BIG CORE REFACTORING: + - get testcases to pass again (!) + - fix transport service API (ATS!) + - fix transport plugin API (ATS!) + - actually transmit ATS data through core API + - fix FS 'latency' ATS function + - fix DV * Integration test: - test bootstrapping via hostlist + transport/core/dht connect diff --git a/src/Makefile.am b/src/Makefile.am index 97a9e8992..3e56a2bcb 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -28,7 +28,7 @@ SUBDIRS = \ peerinfo-tool \ core \ testing \ - dv \ + $(dv) \ dht \ hostlist \ topology \ diff --git a/src/core/Makefile.am b/src/core/Makefile.am index ded3d476c..94db94959 100644 --- a/src/core/Makefile.am +++ b/src/core/Makefile.am @@ -14,10 +14,7 @@ lib_LTLIBRARIES = \ libgnunetcore.la libgnunetcore_la_SOURCES = \ - core_api.c core.h \ - core_api_peer_get_info.c \ - core_api_peer_request.c \ - core_api_iterate_peers.c + core_api.c core.h libgnunetcore_la_LIBADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(GN_LIBINTL) $(XLIB) diff --git a/src/core/core.h b/src/core/core.h index 021aa4184..a8d90b81a 100644 --- a/src/core/core.h +++ b/src/core/core.h @@ -22,6 +22,17 @@ * @file core/core.h * @brief common internal definitions for core service * @author Christian Grothoff + * + * TODO: + * - bound message queue size + * - on disconnect from core, signal disconnect for all peers + * and clean up peer records + * - create / destroy peer records on connect/disconnect events + * - implement iterator API + * - implement re-configure API + * - check on peer-related events that connection is known + * (if not, GNUNET_break + reconnect) + * - handle atsi records */ #include "gnunet_bandwidth_lib.h" #include "gnunet_crypto_lib.h" @@ -112,9 +123,10 @@ struct ConnectNotifyMessage struct GNUNET_MessageHeader header; /** - * Distance to the peer. + * Number of ATS key-value pairs that follow this struct + * (excluding the 0-terminator). */ - uint32_t distance GNUNET_PACKED; + uint32_t ats_count GNUNET_PACKED; /** * Currently observed latency. @@ -126,6 +138,12 @@ struct ConnectNotifyMessage */ struct GNUNET_PeerIdentity peer; + /** + * First of the ATS information blocks (we must have at least + * one due to the 0-termination requirement). + */ + struct GNUNET_TRANSPORT_ATS_Information ats; + }; @@ -141,14 +159,10 @@ struct PeerStatusNotifyMessage struct GNUNET_MessageHeader header; /** - * Distance to the peer. - */ - uint32_t distance GNUNET_PACKED; - - /** - * Currently observed latency. + * Number of ATS key-value pairs that follow this struct + * (excluding the 0-terminator). */ - struct GNUNET_TIME_RelativeNBO latency; + uint32_t ats_count GNUNET_PACKED; /** * When the peer would time out (unless we see activity) @@ -170,6 +184,12 @@ struct PeerStatusNotifyMessage */ struct GNUNET_PeerIdentity peer; + /** + * First of the ATS information blocks (we must have at least + * one due to the 0-termination requirement). + */ + struct GNUNET_TRANSPORT_ATS_Information ats; + }; @@ -197,7 +217,6 @@ struct DisconnectNotifyMessage }; - /** * Message sent by the service to clients to notify them about * messages being received or transmitted. This overall message is @@ -216,9 +235,10 @@ struct NotifyTrafficMessage struct GNUNET_MessageHeader header; /** - * Distance to the peer. + * Number of ATS key-value pairs that follow this struct + * (excluding the 0-terminator). */ - uint32_t distance GNUNET_PACKED; + uint32_t ats_count GNUNET_PACKED; /** * Currently observed latency. @@ -230,6 +250,12 @@ struct NotifyTrafficMessage */ struct GNUNET_PeerIdentity peer; + /** + * First of the ATS information blocks (we must have at least + * one due to the 0-termination requirement). + */ + struct GNUNET_TRANSPORT_ATS_Information ats; + }; @@ -245,9 +271,9 @@ struct RequestInfoMessage struct GNUNET_MessageHeader header; /** - * Always zero. + * Unique request ID. */ - uint32_t reserved GNUNET_PACKED; + uint32_t rim_id GNUNET_PACKED; /** * Limit the number of bytes of outbound traffic to this @@ -296,10 +322,9 @@ struct ConfigurationInfoMessage int32_t reserved_amount GNUNET_PACKED; /** - * Available bandwidth in for this peer. - * 0 if we have been disconnected. + * Unique request ID. */ - struct GNUNET_BANDWIDTH_Value32NBO bw_in; + uint32_t rim_id GNUNET_PACKED; /** * Available bandwidth out for this peer, @@ -314,7 +339,85 @@ struct ConfigurationInfoMessage uint64_t preference; /** - * Identity of the receiver or sender. + * Identity of the peer. + */ + struct GNUNET_PeerIdentity peer; + +}; + + +/** + * Client notifying core about the maximum-priority + * message it has in the queue for a particular target. + */ +struct SendMessageRequest +{ + /** + * Header with type GNUNET_MESSAGE_TYPE_CORE_SEND_REQUEST + */ + struct GNUNET_MessageHeader header; + + /** + * How important is this message? + */ + uint32_t priority GNUNET_PACKED; + + /** + * By what time would the sender really like to see this + * message transmitted? + */ + struct GNUNET_TIME_AbsoluteNBO deadline; + + /** + * Identity of the intended target. + */ + struct GNUNET_PeerIdentity peer; + + /** + * How large is the client's message queue for this peer? + */ + uint32_t queue_size GNUNET_PACKED; + + /** + * How large is the message? + */ + uint16_t size GNUNET_PACKED; + + /** + * Counter for this peer to match SMRs to replies. + */ + uint16_t smr_id GNUNET_PACKED; + +}; + + +/** + * Core notifying client that it is allowed to now + * transmit a message to the given target + * (response to GNUNET_MESSAGE_TYPE_CORE_SEND_REQUEST). + */ +struct SendMessageReady +{ + /** + * Header with type GNUNET_MESSAGE_TYPE_CORE_SEND_READY + */ + struct GNUNET_MessageHeader header; + + /** + * How many bytes are allowed for transmission? + * Guaranteed to be at least as big as the requested size, + * or ZERO if the request is rejected (will timeout, + * peer disconnected, queue full, etc.). + */ + uint16_t size GNUNET_PACKED; + + /** + * smr_id from the request. + */ + uint16_t smr_id GNUNET_PACKED; + + /** + * Identity of the intended target. */ struct GNUNET_PeerIdentity peer; @@ -322,8 +425,8 @@ struct ConfigurationInfoMessage /** - * Client asking core to transmit a particular message to - * a particular target. + * Client asking core to transmit a particular message to a particular + * target (responsde to GNUNET_MESSAGE_TYPE_CORE_SEND_READY). */ struct SendMessage { diff --git a/src/core/core_api.c b/src/core/core_api.c index a1e6aea65..9500a1316 100644 --- a/src/core/core_api.c +++ b/src/core/core_api.c @@ -23,6 +23,9 @@ * @brief core service; this is the main API for encrypted P2P * communications * @author Christian Grothoff + * + * TODO: + * - implement atsi parsing and passing */ #include "platform.h" #include "gnunet_constants.h" @@ -30,13 +33,125 @@ #include "core.h" +/** + * Information we track for each peer. + */ +struct PeerRecord +{ + + /** + * We generally do NOT keep peer records in a DLL; this + * DLL is only used IF this peer's 'pending_head' message + * is ready for transmission. + */ + struct PeerRecord *prev; + + /** + * We generally do NOT keep peer records in a DLL; this + * DLL is only used IF this peer's 'pending_head' message + * is ready for transmission. + */ + struct PeerRecord *next; + + /** + * Peer the record is about. + */ + struct GNUNET_PeerIdentity peer; + + /** + * Corresponding core handle. + */ + struct GNUNET_CORE_Handle *ch; + + /** + * Head of doubly-linked list of pending requests. + * Requests are sorted by deadline *except* for HEAD, + * which is only modified upon transmission to core. + */ + struct GNUNET_CORE_TransmitHandle *pending_head; + + /** + * Tail of doubly-linked list of pending requests. + */ + struct GNUNET_CORE_TransmitHandle *pending_tail; + + /** + * Pending callback waiting for peer information, or NULL for none. + */ + GNUNET_CORE_PeerConfigurationInfoCallback pcic; + + /** + * Closure for pcic. + */ + void *pcic_cls; + + /** + * Request information ID for the given pcic (needed in case a + * request is cancelled after being submitted to core and a new + * one is generated; in this case, we need to avoid matching the + * reply to the first (cancelled) request to the second request). + */ + uint32_t rim_id; + + /** + * ID of timeout task for the 'pending_head' handle + * which is the one with the smallest timeout. + */ + GNUNET_SCHEDULER_TaskIdentifier timeout_task; + + /** + * Current size of the queue of pending requests. + */ + unsigned int queue_size; + + /** + * SendMessageRequest ID generator for this peer. + */ + uint16_t smr_id_gen; + +}; + + +/** + * Entry in a doubly-linked list of control messages to be transmitted + * to the core service. Control messages include traffic allocation, + * connection requests and of course our initial 'init' request. + * + * The actual message is allocated at the end of this struct. + */ +struct ControlMessage +{ + /** + * This is a doubly-linked list. + */ + struct ControlMessage *next; + + /** + * This is a doubly-linked list. + */ + struct ControlMessage *prev; + + /** + * Function to run after successful transmission (or call with + * reason 'TIMEOUT' on error). + */ + GNUNET_SCHEDULER_Task cont; + + /** + * Closure for 'cont'. + */ + void *cont_cls; + +}; + + + /** * Context for the core service connection. */ struct GNUNET_CORE_Handle { - /** * Configuration we're using. */ @@ -83,9 +198,9 @@ struct GNUNET_CORE_Handle const struct GNUNET_CORE_MessageHandler *handlers; /** - * Our connection to the service for notifications. + * Our connection to the service. */ - struct GNUNET_CLIENT_Connection *client_notifications; + struct GNUNET_CLIENT_Connection *client; /** * Handle for our current transmission request. @@ -95,41 +210,43 @@ struct GNUNET_CORE_Handle /** * Head of doubly-linked list of pending requests. */ - struct GNUNET_CORE_TransmitHandle *pending_head; + struct ControlMessage *pending_head; /** * Tail of doubly-linked list of pending requests. */ - struct GNUNET_CORE_TransmitHandle *pending_tail; + struct ControlMessage *pending_tail; /** - * Currently submitted request (or NULL) + * Head of doubly-linked list of peers that are core-approved + * to send their next message. */ - struct GNUNET_CORE_TransmitHandle *submitted; + struct PeerRecord *ready_peer_head; /** - * Currently submitted request based on solicitation (or NULL) + * Tail of doubly-linked list of peers that are core-approved + * to send their next message. */ - struct GNUNET_CORE_TransmitHandle *solicit_transmit_req; + struct PeerRecord *ready_peer_tail; /** - * Buffer where we store a message for transmission in response - * to a traffic solicitation (or NULL). + * Hash map listing all of the peers that we are currently + * connected to. */ - char *solicit_buffer; + struct GNUNET_CONTAINER_MultiHashMap *peers; /** - * How long to wait until we time out the connection attempt? + * ID of reconnect task (if any). */ - struct GNUNET_TIME_Absolute startup_timeout; + GNUNET_SCHEDULER_TaskIdentifier reconnect_task; /** - * ID of reconnect task (if any). + * Request information ID generator. */ - GNUNET_SCHEDULER_TaskIdentifier reconnect_task; + uint32_t rim_id_gen; /** - * Number of messages we should queue per target. + * Number of messages we are allowed to queue per target. */ unsigned int queue_size; @@ -155,6 +272,7 @@ struct GNUNET_CORE_Handle * requests? */ int currently_down; + }; @@ -175,9 +293,15 @@ struct GNUNET_CORE_TransmitHandle struct GNUNET_CORE_TransmitHandle *prev; /** - * Corresponding core handle. + * Corresponding peer record. */ - struct GNUNET_CORE_Handle *ch; + struct PeerRecord *peer; + + /** + * Corresponding SEND_REQUEST message. Only non-NULL + * while SEND_REQUEST message is pending. + */ + struct ControlMessage *cm; /** * Function that will be called to get the actual request @@ -192,32 +316,11 @@ struct GNUNET_CORE_TransmitHandle */ void *get_message_cls; - /** - * If this entry is for a transmission request, pointer - * to the notify callback; otherwise NULL. - */ - GNUNET_CONNECTION_TransmitReadyNotify notify; - - /** - * Closure for notify. - */ - void *notify_cls; - - /** - * Peer the request is about. - */ - struct GNUNET_PeerIdentity peer; - /** * Timeout for this handle. */ struct GNUNET_TIME_Absolute timeout; - /** - * ID of timeout task. - */ - GNUNET_SCHEDULER_TaskIdentifier timeout_task; - /** * How important is this message? */ @@ -228,54 +331,127 @@ struct GNUNET_CORE_TransmitHandle */ uint16_t msize; + /** + * Send message request ID for this request. + */ + uint16_t smr_id; }; +/** + * Our current client connection went down. Clean it up + * and try to reconnect! + * + * @param h our handle to the core service + */ static void -reconnect_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc); +reconnect (struct GNUNET_CORE_Handle *h); /** - * Function called when we are ready to transmit our - * "START" message (or when this operation timed out). + * Task schedule to try to re-connect to core. * - * @param cls closure - * @param size number of bytes available in buf - * @param buf where the callee should write the message - * @return number of bytes written to buf + * @param cls the 'struct GNUNET_CORE_Handle' + * @param tc task context */ -static size_t transmit_start (void *cls, size_t size, void *buf); +static void +reconnect_task (void *cls, + const struct GNUNET_SCHEDULER_TaskContext *tc) +{ + struct GNUNET_CORE_Handle *h = cls; + + h->reconnect_task = GNUNET_SCHEDULER_NO_TASK; + reconnect (h); +} /** - * Our current client connection went down. Clean it up - * and try to reconnect! + * Check the list of pending requests, send the next + * one to the core. * - * @param h our handle to the core service + * @param h core handle */ static void -reconnect (struct GNUNET_CORE_Handle *h) +trigger_next_request (struct GNUNET_CORE_Handle *h); + + +/** + * The given request hit its timeout. Remove from the + * doubly-linked list and call the respective continuation. + * + * @param cls the transmit handle of the request that timed out + * @param tc context, can be NULL (!) + */ +static void +transmission_timeout (void *cls, + const struct GNUNET_SCHEDULER_TaskContext *tc); + + +/** + * Control message was sent, mark it as such. + * + * @param cls the 'struct GNUNET_CORE_TransmitHandle*' + * @param tc scheduler context + */ +static void +mark_control_message_sent (void *cls, + const struct GNUNET_SCHEDULER_TaskContext *tc) { -#if DEBUG_CORE - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Reconnecting to CORE service\n"); -#endif - if (h->client_notifications != NULL) - GNUNET_CLIENT_disconnect (h->client_notifications, GNUNET_NO); - h->currently_down = GNUNET_YES; - h->client_notifications = GNUNET_CLIENT_connect ("core", h->cfg); - if (h->client_notifications == NULL) - h->reconnect_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS, - &reconnect_task, - h); - else - h->cth = GNUNET_CLIENT_notify_transmit_ready (h->client_notifications, - sizeof (struct InitMessage) + - sizeof (uint16_t) * h->hcnt, - GNUNET_TIME_UNIT_SECONDS, - GNUNET_NO, - &transmit_start, h); + struct GNUNET_CORE_TransmitHandle *th = cls; + + th->cm = NULL; +} + + +/** + * Send a control message to the peer asking for transmission + * of the message in the given peer record. + * + * @param pr peer to request transmission to + */ +static void +request_next_transmission (struct PeerRecord *pr) +{ + struct GNUNET_CORE_Handle *h = pr->ch; + struct ControlMessage *cm; + struct SendMessageRequest *smr; + struct GNUNET_CORE_TransmitHandle *th; + + if (pr->timeout_task != GNUNET_SCHEDULER_NO_TASK) + { + GNUNET_SCHEDULER_cancel (pr->timeout_task); + pr->timeout_task = GNUNET_SCHEDULER_NO_TASK; + } + if (NULL == (th = pr->pending_head)) + { + trigger_next_request (h); + return; + } + GNUNET_assert (pr->prev == NULL); + GNUNET_assert (pr->next == NULL); + pr->timeout_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_absolute_get_remaining (th->timeout), + &transmission_timeout, + pr); + cm = GNUNET_malloc (sizeof (struct ControlMessage) + + sizeof (struct SendMessageRequest)); + cm->cont = &mark_control_message_sent; + cm->cont_cls = th; + th->cm = cm; + smr = (struct SendMessageRequest*) &cm[1]; + smr->header.type = htons (GNUNET_MESSAGE_TYPE_CORE_SEND_REQUEST); + smr->header.size = htons (sizeof (struct SendMessageRequest)); + smr->priority = htonl (th->priority); + smr->deadline = GNUNET_TIME_absolute_hton (th->timeout); + smr->peer = pr->peer; + 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, + cm); + trigger_next_request (h); } @@ -287,97 +463,225 @@ reconnect (struct GNUNET_CORE_Handle *h) * @param tc context, can be NULL (!) */ static void -timeout_request (void *cls, - const struct GNUNET_SCHEDULER_TaskContext *tc) +transmission_timeout (void *cls, + const struct GNUNET_SCHEDULER_TaskContext *tc) { - struct GNUNET_CORE_TransmitHandle *th = cls; + struct PeerRecord *pr = cls; + struct GNUNET_CORE_TransmitHandle *th; - th->timeout_task = GNUNET_SCHEDULER_NO_TASK; - GNUNET_CONTAINER_DLL_remove (th->ch->pending_head, - th->ch->pending_tail, + pr->timeout_task = GNUNET_SCHEDULER_NO_TASK; + th = pr->pending_head; + GNUNET_CONTAINER_DLL_remove (pr->pending_head, + pr->pending_tail, th); + pr->queue_size--; #if DEBUG_CORE GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Signalling timeout of request for transmission to CORE service\n"); #endif GNUNET_assert (0 == th->get_message (th->get_message_cls, 0, NULL)); + request_next_transmission (pr); } /** - * Function called when we are ready to transmit a request from our - * request list (or when this operation timed out). - * - * @param cls closure - * @param size number of bytes available in buf - * @param buf where the callee should write the message - * @return number of bytes written to buf + * Transmit the next message to the core service. */ static size_t -request_start (void *cls, size_t size, void *buf) +transmit_message (void *cls, + size_t size, + void *buf) { struct GNUNET_CORE_Handle *h = cls; + struct ControlMessage *cm; struct GNUNET_CORE_TransmitHandle *th; + struct PeerRecord *pr; + struct SendMessage *sm; + const struct GNUNET_MessageHeader *hdr; + uint16_t msize; size_t ret; - h->cth = NULL; - th = h->pending_head; - if (th == NULL) - return 0; + h->cth = NULL; if (buf == NULL) { - if (th->timeout_task != GNUNET_SCHEDULER_NO_TASK) + reconnect (h); + return 0; + } + /* first check for control messages */ + if (NULL != (cm = h->pending_head)) + { + hdr = (const struct GNUNET_MessageHeader*) &cm[1]; + msize = ntohs (hdr->size); + if (size < msize) { - GNUNET_SCHEDULER_cancel(th->timeout_task); - th->timeout_task = GNUNET_SCHEDULER_NO_TASK; + trigger_next_request (h); + return 0; } - timeout_request (th, NULL); - return 0; + memcpy (buf, hdr, msize); + GNUNET_CONTAINER_DLL_remove (h->pending_head, + h->pending_tail, + cm); + if (NULL != cm->cont) + GNUNET_SCHEDULER_add_now (cm->cont, cm->cont_cls); + GNUNET_free (cm); + trigger_next_request (h); + return msize; } - GNUNET_CONTAINER_DLL_remove (h->pending_head, - h->pending_tail, - th); - GNUNET_assert (h->submitted == NULL); - h->submitted = th; - GNUNET_assert (size >= th->msize); - ret = th->get_message (th->get_message_cls, size, buf); - GNUNET_assert (ret <= size); + /* now check for 'ready' P2P messages */ + if (NULL != (pr = h->ready_peer_head)) + { + th = pr->pending_head; + if (size < th->msize + sizeof (struct SendMessage)) + { + trigger_next_request (h); + return 0; + } + GNUNET_CONTAINER_DLL_remove (h->ready_peer_head, + h->ready_peer_tail, + pr); + GNUNET_CONTAINER_DLL_remove (pr->pending_head, + pr->pending_tail, + th); + pr->queue_size--; + if (pr->timeout_task != GNUNET_SCHEDULER_NO_TASK) + { + GNUNET_SCHEDULER_cancel (pr->timeout_task); + pr->timeout_task = GNUNET_SCHEDULER_NO_TASK; + } + + sm = (struct SendMessage *) buf; + sm->header.type = htons (GNUNET_MESSAGE_TYPE_CORE_SEND); + sm->priority = htonl (th->priority); + sm->deadline = GNUNET_TIME_absolute_hton (th->timeout); + sm->peer = pr->peer; + ret = th->get_message (th->get_message_cls, + size - sizeof (struct SendMessage), + &sm[1]); + + if (0 == ret) + { #if DEBUG_CORE - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Transmitting %u bytes to core\n", - ret); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Size of clients message to peer %s is 0!\n", + GNUNET_i2s(&pr->peer)); #endif - return ret; + /* client decided to send nothing! */ + request_next_transmission (pr); + return 0; + } +#if DEBUG_CORE + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Produced SEND message to core with %u bytes payload\n", + (unsigned int) ret); +#endif + GNUNET_assert (ret >= sizeof (struct GNUNET_MessageHeader)); + if (ret + sizeof (struct SendMessage) >= GNUNET_SERVER_MAX_MESSAGE_SIZE) + { + GNUNET_break (0); + request_next_transmission (pr); + return 0; + } + ret += sizeof (struct SendMessage); + sm->header.size = htons (ret); + GNUNET_assert (ret <= size); + GNUNET_free (th); + request_next_transmission (pr); + return ret; + } + return 0; } /** * Check the list of pending requests, send the next * one to the core. + * + * @param h core handle */ static void trigger_next_request (struct GNUNET_CORE_Handle *h) { + uint16_t msize; + + if (GNUNET_YES == h->currently_down) + return; + if (NULL != h->cth) + return; + if (h->pending_head != NULL) + msize = ntohs (((struct GNUNET_MessageHeader*) &h->pending_head[1])->size); + else if (h->ready_peer_head != NULL) + msize = h->ready_peer_head->pending_head->msize + sizeof (struct SendMessage); + else + return; /* no pending message */ + h->cth = GNUNET_CLIENT_notify_transmit_ready (h->client, + msize, + GNUNET_TIME_UNIT_FOREVER_REL, + GNUNET_NO, + &transmit_message, h); +} + + + + +/** + * Notify clients about disconnect and free + * the entry for connected peer. + * + * @param cls the 'struct GNUNET_CORE_Handle*' + * @param key the peer identity (not used) + * @param value the 'struct PeerRecord' to free. + * @return GNUNET_YES (continue) + */ +static int +disconnect_and_free_peer_entry (void *cls, + const GNUNET_HashCode *key, + void *value) +{ + struct GNUNET_CORE_Handle *h = cls; struct GNUNET_CORE_TransmitHandle *th; + struct PeerRecord *pr = value; - if (h->currently_down) + while (NULL != (th = pr->pending_head)) { -#if DEBUG_CORE - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "In trigger_next_request, connection currently down...\n"); -#endif - return; /* connection temporarily down */ + GNUNET_CONTAINER_DLL_remove (pr->pending_head, + pr->pending_tail, + th); + pr->queue_size--; + GNUNET_assert (0 == + th->get_message (th->get_message_cls, + 0, NULL)); + GNUNET_free (th); } - if (NULL == (th = h->pending_head)) - return; /* no requests pending */ - GNUNET_assert (NULL == h->cth); - h->cth = GNUNET_CLIENT_notify_transmit_ready (h->client_notifications, - th->msize, - GNUNET_TIME_absolute_get_remaining - (th->timeout), - GNUNET_NO, - &request_start, - h); + if (pr->pcic != NULL) + { + // FIXME: call pcic callback! + } + if (pr->timeout_task != GNUNET_SCHEDULER_NO_TASK) + { + GNUNET_SCHEDULER_cancel (pr->timeout_task); + pr->timeout_task = GNUNET_SCHEDULER_NO_TASK; + } + GNUNET_assert (pr->queue_size == 0); + if ( (pr->prev != NULL) || + (pr->next != NULL) || + (h->ready_peer_head == pr) ) + GNUNET_CONTAINER_DLL_remove (h->ready_peer_head, + h->ready_peer_tail, + pr); + if (h->disconnects != NULL) + h->disconnects (h->cls, + &pr->peer); + GNUNET_assert (GNUNET_YES == + GNUNET_CONTAINER_multihashmap_remove (h->peers, + key, + pr)); + GNUNET_assert (pr->pending_head == NULL); + GNUNET_assert (pr->pending_tail == NULL); + GNUNET_assert (pr->ch = h); + GNUNET_assert (pr->queue_size == 0); + GNUNET_assert (pr->timeout_task == GNUNET_SCHEDULER_NO_TASK); + GNUNET_free (pr); + return GNUNET_YES; } @@ -388,18 +692,28 @@ trigger_next_request (struct GNUNET_CORE_Handle *h) * @param msg the message received from the core service */ static void -main_notify_handler (void *cls, const struct GNUNET_MessageHeader *msg) +main_notify_handler (void *cls, + const struct GNUNET_MessageHeader *msg) { struct GNUNET_CORE_Handle *h = cls; - unsigned int hpos; + const struct InitReplyMessage *m; const struct ConnectNotifyMessage *cnm; const struct DisconnectNotifyMessage *dnm; const struct NotifyTrafficMessage *ntm; const struct GNUNET_MessageHeader *em; + const struct ConfigurationInfoMessage *cim; const struct PeerStatusNotifyMessage *psnm; + const struct SendMessageReady *smr; + const struct GNUNET_CORE_MessageHandler *mh; + GNUNET_CORE_StartupCallback init; + GNUNET_CORE_PeerConfigurationInfoCallback pcic; + struct GNUNET_PeerIdentity my_identity; + struct PeerRecord *pr; + struct GNUNET_CORE_TransmitHandle *th; + unsigned int hpos; + int trigger; uint16_t msize; uint16_t et; - const struct GNUNET_CORE_MessageHandler *mh; if (msg == NULL) { @@ -417,37 +731,85 @@ main_notify_handler (void *cls, const struct GNUNET_MessageHeader *msg) #endif switch (ntohs (msg->type)) { + case GNUNET_MESSAGE_TYPE_CORE_INIT_REPLY: + if (ntohs (msg->size) != sizeof (struct InitReplyMessage)) + { + GNUNET_break (0); + reconnect (h); + return; + } + m = (const struct InitReplyMessage *) msg; + GNUNET_break (0 == ntohl (m->reserved)); + /* start our message processing loop */ +#if DEBUG_CORE + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Successfully connected to core service, starting processing loop.\n"); +#endif + if (GNUNET_YES == h->currently_down) + { + h->currently_down = GNUNET_NO; + trigger_next_request (h); + } + if (NULL != (init = h->init)) + { + /* mark so we don't call init on reconnect */ + h->init = NULL; + GNUNET_CRYPTO_hash (&m->publicKey, + sizeof (struct + GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded), + &my_identity.hashPubKey); + init (h->cls, h, &my_identity, &m->publicKey); + } + break; case GNUNET_MESSAGE_TYPE_CORE_NOTIFY_CONNECT: - if (NULL == h->connects) - { - GNUNET_break (0); - break; - } if (msize != sizeof (struct ConnectNotifyMessage)) { GNUNET_break (0); break; } cnm = (const struct ConnectNotifyMessage *) msg; - h->connects (h->cls, - &cnm->peer, - GNUNET_TIME_relative_ntoh (cnm->latency), - ntohl (cnm->distance)); + pr = GNUNET_CONTAINER_multihashmap_get (h->peers, + &cnm->peer.hashPubKey); + if (pr != NULL) + { + GNUNET_break (0); + reconnect (h); + return; + } + pr = GNUNET_malloc (sizeof (struct PeerRecord)); + pr->peer = cnm->peer; + pr->ch = h; + GNUNET_assert (GNUNET_YES == + GNUNET_CONTAINER_multihashmap_put (h->peers, + &cnm->peer.hashPubKey, + pr, + GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST)); + if (NULL != h->connects) + h->connects (h->cls, + &cnm->peer, + NULL /* FIXME: atsi! */); break; case GNUNET_MESSAGE_TYPE_CORE_NOTIFY_DISCONNECT: - if (NULL == h->disconnects) - { - GNUNET_break (0); - break; - } if (msize != sizeof (struct DisconnectNotifyMessage)) { GNUNET_break (0); break; } dnm = (const struct DisconnectNotifyMessage *) msg; - h->disconnects (h->cls, - &dnm->peer); + pr = GNUNET_CONTAINER_multihashmap_get (h->peers, + &dnm->peer.hashPubKey); + if (pr == NULL) + { + GNUNET_break (0); + reconnect (h); + return; + } + trigger = ( (pr->prev != NULL) || + (pr->next != NULL) || + (h->ready_peer_head == pr) ); + disconnect_and_free_peer_entry (h, &dnm->peer.hashPubKey, pr); + if (trigger) + trigger_next_request (h); break; case GNUNET_MESSAGE_TYPE_CORE_NOTIFY_STATUS_CHANGE: if (NULL == h->status_events) @@ -461,13 +823,20 @@ main_notify_handler (void *cls, const struct GNUNET_MessageHeader *msg) break; } psnm = (const struct PeerStatusNotifyMessage *) msg; + pr = GNUNET_CONTAINER_multihashmap_get (h->peers, + &psnm->peer.hashPubKey); + if (pr == NULL) + { + GNUNET_break (0); + reconnect (h); + return; + } h->status_events (h->cls, &psnm->peer, - GNUNET_TIME_relative_ntoh (psnm->latency), - ntohl (psnm->distance), psnm->bandwidth_in, psnm->bandwidth_out, - GNUNET_TIME_absolute_ntoh (psnm->timeout)); + GNUNET_TIME_absolute_ntoh (psnm->timeout), + NULL /* FIXME: atsi */); break; case GNUNET_MESSAGE_TYPE_CORE_NOTIFY_INBOUND: if (msize < @@ -486,6 +855,14 @@ main_notify_handler (void *cls, const struct GNUNET_MessageHeader *msg) ntohs (em->size), GNUNET_i2s (&ntm->peer)); #endif + pr = GNUNET_CONTAINER_multihashmap_get (h->peers, + &ntm->peer.hashPubKey); + if (pr == NULL) + { + GNUNET_break (0); + reconnect (h); + return; + } if ((GNUNET_NO == h->inbound_hdr_only) && (msize != ntohs (em->size) + sizeof (struct NotifyTrafficMessage))) { @@ -506,8 +883,7 @@ main_notify_handler (void *cls, const struct GNUNET_MessageHeader *msg) } if (GNUNET_OK != h->handlers[hpos].callback (h->cls, &ntm->peer, em, - GNUNET_TIME_relative_ntoh (ntm->latency), - ntohl (ntm->distance))) + NULL /* FIXME: atsi */)) { /* error in processing, do not process other messages! */ break; @@ -515,8 +891,7 @@ main_notify_handler (void *cls, const struct GNUNET_MessageHeader *msg) } if (NULL != h->inbound_notify) h->inbound_notify (h->cls, &ntm->peer, em, - GNUNET_TIME_relative_ntoh (ntm->latency), - ntohl (ntm->distance)); + NULL /* FIXME: atsi */); break; case GNUNET_MESSAGE_TYPE_CORE_NOTIFY_OUTBOUND: if (msize < @@ -528,7 +903,15 @@ main_notify_handler (void *cls, const struct GNUNET_MessageHeader *msg) } ntm = (const struct NotifyTrafficMessage *) msg; em = (const struct GNUNET_MessageHeader *) &ntm[1]; - if ((GNUNET_NO == h->outbound_hdr_only) && + pr = GNUNET_CONTAINER_multihashmap_get (h->peers, + &ntm->peer.hashPubKey); + if (pr == NULL) + { + GNUNET_break (0); + reconnect (h); + return; + } + if ((GNUNET_NO == h->outbound_hdr_only) && (msize != ntohs (em->size) + sizeof (struct NotifyTrafficMessage))) { GNUNET_break (0); @@ -540,159 +923,157 @@ main_notify_handler (void *cls, const struct GNUNET_MessageHeader *msg) break; } h->outbound_notify (h->cls, &ntm->peer, em, - GNUNET_TIME_relative_ntoh (ntm->latency), - ntohl (ntm->distance)); + NULL /* FIXME: atsi? */); + break; + case GNUNET_MESSAGE_TYPE_CORE_SEND_READY: + if (msize != sizeof (struct SendMessageReady)) + { + GNUNET_break (0); + break; + } + smr = (const struct SendMessageReady *) msg; + pr = GNUNET_CONTAINER_multihashmap_get (h->peers, + &smr->peer.hashPubKey); + if (pr == NULL) + { + GNUNET_break (0); + reconnect (h); + return; + } + th = pr->pending_head; + if (ntohs (smr->smr_id) != th->smr_id) + { + /* READY message is for expired or cancelled message, + ignore! (we should have already sent another request) */ + break; + } + if ( (pr->prev != NULL) || + (pr->next != NULL) || + (h->ready_peer_head == pr) ) + { + /* we should not already be on the ready list... */ + GNUNET_break (0); + reconnect (h); + return; + } + GNUNET_CONTAINER_DLL_insert (h->ready_peer_head, + h->ready_peer_tail, + pr); + trigger_next_request (h); + break; + case GNUNET_MESSAGE_TYPE_CORE_CONFIGURATION_INFO: + if (ntohs (msg->size) != sizeof (struct ConfigurationInfoMessage)) + { + GNUNET_break (0); + break; + } + cim = (const struct ConfigurationInfoMessage*) msg; + pr = GNUNET_CONTAINER_multihashmap_get (h->peers, + &cim->peer.hashPubKey); + if (pr == NULL) + { + GNUNET_break (0); + reconnect (h); + return; + } + if (pr->rim_id != ntohl (cim->rim_id)) + break; + pcic = pr->pcic; + pr->pcic = NULL; + if (pcic != NULL) + pcic (pr->pcic_cls, + &pr->peer, + cim->bw_out, + ntohl (cim->reserved_amount), + GNUNET_ntohll (cim->preference)); break; default: GNUNET_break (0); break; } - GNUNET_CLIENT_receive (h->client_notifications, + GNUNET_CLIENT_receive (h->client, &main_notify_handler, h, GNUNET_TIME_UNIT_FOREVER_REL); } /** - * Function called when we are ready to transmit our - * "START" message (or when this operation timed out). - * - * @param cls closure - * @param size number of bytes available in buf - * @param buf where the callee should write the message - * @return number of bytes written to buf - */ -static size_t transmit_start (void *cls, size_t size, void *buf); - - -/** - * Function called on the first message received from - * the service (contains our public key, etc.). - * Should trigger calling the init callback - * and then start our regular message processing. + * Task executed once we are done transmitting the INIT message. + * Starts our 'receive' loop. * - * @param cls closure - * @param msg message received, NULL on timeout or fatal error + * @param cls the 'struct GNUNET_CORE_Handle' + * @param tc task context */ static void -init_reply_handler (void *cls, const struct GNUNET_MessageHeader *msg) +init_done_task (void *cls, + const struct GNUNET_SCHEDULER_TaskContext *tc) { struct GNUNET_CORE_Handle *h = cls; - const struct InitReplyMessage *m; - GNUNET_CORE_StartupCallback init; - struct GNUNET_PeerIdentity my_identity; - if ((msg == NULL) || - (ntohs (msg->size) != sizeof (struct InitReplyMessage)) || - (ntohs (msg->type) != GNUNET_MESSAGE_TYPE_CORE_INIT_REPLY)) + if (0 == (tc->reason & GNUNET_SCHEDULER_REASON_PREREQ_DONE)) { - if (msg != NULL) + if (h->client != NULL) { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - _ - ("Error connecting to core service (failed to receive `%s' message, got message of type %u and size %u).\n"), - "INIT_REPLY", - ntohs (msg->type), - ntohs (msg->size)); - GNUNET_break (0); + GNUNET_CLIENT_disconnect (h->client, GNUNET_NO); + h->client = NULL; } - else - { -#if DEBUG_CORE - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - _("Failed to connect to core service, will retry.\n")); -#endif - } - transmit_start (h, 0, NULL); + h->reconnect_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS, + &reconnect_task, + h); return; } - m = (const struct InitReplyMessage *) msg; - GNUNET_break (0 == ntohl (m->reserved)); - /* start our message processing loop */ -#if DEBUG_CORE - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Successfully connected to core service, starting processing loop.\n"); -#endif - h->currently_down = GNUNET_NO; - trigger_next_request (h); - GNUNET_CLIENT_receive (h->client_notifications, - &main_notify_handler, h, GNUNET_TIME_UNIT_FOREVER_REL); - if (NULL != (init = h->init)) - { - /* mark so we don't call init on reconnect */ - h->init = NULL; - GNUNET_CRYPTO_hash (&m->publicKey, - sizeof (struct - GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded), - &my_identity.hashPubKey); - init (h->cls, h, &my_identity, &m->publicKey); - } -} - - -static void -reconnect_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) -{ - struct GNUNET_CORE_Handle *h = cls; - h->reconnect_task = GNUNET_SCHEDULER_NO_TASK; - reconnect (h); + GNUNET_CLIENT_receive (h->client, + &main_notify_handler, + h, + GNUNET_TIME_UNIT_FOREVER_REL); } /** - * Function called when we are ready to transmit our - * "START" message (or when this operation timed out). + * Our current client connection went down. Clean it up + * and try to reconnect! * - * @param cls closure - * @param size number of bytes available in buf - * @param buf where the callee should write the message - * @return number of bytes written to buf + * @param h our handle to the core service */ -static size_t -transmit_start (void *cls, size_t size, void *buf) +static void +reconnect (struct GNUNET_CORE_Handle *h) { - struct GNUNET_CORE_Handle *h = cls; + struct ControlMessage *cm; struct InitMessage *init; - uint16_t *ts; - uint16_t msize; uint32_t opt; + uint16_t msize; + uint16_t *ts; unsigned int hpos; - struct GNUNET_TIME_Relative delay; - h->cth = NULL; - if (size == 0) +#if DEBUG_CORE + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Reconnecting to CORE service\n"); +#endif + if (h->client != NULL) { - if ((h->init == NULL) || - (GNUNET_TIME_absolute_get ().abs_value < h->startup_timeout.abs_value)) - { - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - _("Failed to connect to core service, retrying.\n")); - delay = GNUNET_TIME_absolute_get_remaining (h->startup_timeout); - if ((h->init == NULL) || (delay.rel_value > 1000)) - delay = GNUNET_TIME_UNIT_SECONDS; - if (h->init == NULL) - h->startup_timeout = - GNUNET_TIME_relative_to_absolute (GNUNET_TIME_UNIT_MINUTES); - h->reconnect_task = - GNUNET_SCHEDULER_add_delayed (delay, &reconnect_task, h); - return 0; - } - /* timeout on initial connect */ - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - _("Failed to connect to core service, giving up.\n")); - h->init (h->cls, NULL, NULL, NULL); - GNUNET_CORE_disconnect (h); - return 0; + GNUNET_CLIENT_disconnect (h->client, GNUNET_NO); + h->client = NULL; + GNUNET_CONTAINER_multihashmap_iterate (h->peers, + &disconnect_and_free_peer_entry, + h); + } + h->currently_down = GNUNET_YES; + h->client = GNUNET_CLIENT_connect ("core", h->cfg); + if (h->client == NULL) + { + h->reconnect_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS, + &reconnect_task, + h); + return; } msize = h->hcnt * sizeof (uint16_t) + sizeof (struct InitMessage); - GNUNET_assert (size >= msize); - init = buf; + cm = GNUNET_malloc (sizeof (struct ControlMessage) + + msize); + cm->cont = &init_done_task; + cm->cont_cls = h; + init = (struct InitMessage*) &cm[1]; init->header.type = htons (GNUNET_MESSAGE_TYPE_CORE_INIT); init->header.size = htons (msize); - opt = GNUNET_CORE_OPTION_NOTHING; - if (h->connects != NULL) - opt |= GNUNET_CORE_OPTION_SEND_CONNECT; - if (h->disconnects != NULL) - opt |= GNUNET_CORE_OPTION_SEND_DISCONNECT; + opt = GNUNET_CORE_OPTION_SEND_CONNECT | GNUNET_CORE_OPTION_SEND_DISCONNECT; if (h->status_events != NULL) opt |= GNUNET_CORE_OPTION_SEND_STATUS_CHANGE; if (h->inbound_notify != NULL) @@ -710,25 +1091,23 @@ transmit_start (void *cls, size_t size, void *buf) opt |= GNUNET_CORE_OPTION_SEND_FULL_OUTBOUND; } init->options = htonl (opt); - ts = (uint16_t *) & init[1]; + ts = (uint16_t *) &init[1]; for (hpos = 0; hpos < h->hcnt; hpos++) ts[hpos] = htons (h->handlers[hpos].type); - GNUNET_CLIENT_receive (h->client_notifications, - &init_reply_handler, - h, - GNUNET_TIME_absolute_get_remaining - (h->startup_timeout)); - return sizeof (struct InitMessage) + h->hcnt * sizeof (uint16_t); + GNUNET_CONTAINER_DLL_insert (h->pending_head, + h->pending_tail, + cm); + trigger_next_request (h); } + /** * Connect to the core service. Note that the connection may * complete (or fail) asynchronously. * * @param cfg configuration to use * @param queue_size size of the per-peer message queue - * @param timeout after how long should we give up trying to connect to the core service? * @param cls closure for the various callbacks that follow (including handlers in the handlers array) * @param init callback to call on timeout or once we have successfully * connected to the core service; note that timeout is only meaningful if init is not NULL @@ -750,7 +1129,6 @@ transmit_start (void *cls, size_t size, void *buf) struct GNUNET_CORE_Handle * GNUNET_CORE_connect (const struct GNUNET_CONFIGURATION_Handle *cfg, unsigned int queue_size, - struct GNUNET_TIME_Relative timeout, void *cls, GNUNET_CORE_StartupCallback init, GNUNET_CORE_ConnectEventHandler connects, @@ -766,6 +1144,7 @@ GNUNET_CORE_connect (const struct GNUNET_CONFIGURATION_Handle *cfg, h = GNUNET_malloc (sizeof (struct GNUNET_CORE_Handle)); h->cfg = cfg; + h->queue_size = queue_size; h->cls = cls; h->init = init; h->connects = connects; @@ -776,133 +1155,57 @@ GNUNET_CORE_connect (const struct GNUNET_CONFIGURATION_Handle *cfg, h->inbound_hdr_only = inbound_hdr_only; h->outbound_hdr_only = outbound_hdr_only; h->handlers = handlers; - h->queue_size = queue_size; - h->client_notifications = GNUNET_CLIENT_connect ("core", cfg); - if (h->client_notifications == NULL) - { - GNUNET_free (h); - return NULL; - } - h->startup_timeout = GNUNET_TIME_relative_to_absolute (timeout); h->hcnt = 0; while (handlers[h->hcnt].callback != NULL) h->hcnt++; GNUNET_assert (h->hcnt < (GNUNET_SERVER_MAX_MESSAGE_SIZE - sizeof (struct InitMessage)) / sizeof (uint16_t)); -#if DEBUG_CORE - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Trying to connect to core service in next %llu ms.\n", - timeout.rel_value); -#endif - h->cth = - GNUNET_CLIENT_notify_transmit_ready (h->client_notifications, - sizeof (struct InitMessage) + - sizeof (uint16_t) * h->hcnt, timeout, - GNUNET_YES, - &transmit_start, h); + reconnect (h); return h; } /** - * Disconnect from the core service. + * Disconnect from the core service. This function can only + * be called *after* all pending 'GNUNET_CORE_notify_transmit_ready' + * requests have been explicitly cancelled. * * @param handle connection to core to disconnect */ void GNUNET_CORE_disconnect (struct GNUNET_CORE_Handle *handle) { - if (handle->cth != NULL) - GNUNET_CLIENT_notify_transmit_ready_cancel (handle->cth); - if (handle->solicit_transmit_req != NULL) - GNUNET_CORE_notify_transmit_ready_cancel (handle->solicit_transmit_req); + struct ControlMessage *cm; + if (handle->reconnect_task != GNUNET_SCHEDULER_NO_TASK) - GNUNET_SCHEDULER_cancel (handle->reconnect_task); - if (handle->client_notifications != NULL) - GNUNET_CLIENT_disconnect (handle->client_notifications, GNUNET_NO); - GNUNET_break (handle->pending_head == NULL); - GNUNET_free_non_null (handle->solicit_buffer); - GNUNET_free (handle); -} - - -/** - * Build the message requesting data transmission. - */ -static size_t -produce_send (void *cls, size_t size, void *buf) -{ - struct GNUNET_CORE_TransmitHandle *th = cls; - struct GNUNET_CORE_Handle *h; - struct SendMessage *sm; - size_t dt; - GNUNET_CONNECTION_TransmitReadyNotify notify; - void *notify_cls; - - h = th->ch; - if (buf == NULL) { - /* timeout or error */ -#if DEBUG_CORE - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "P2P transmission request for `%4s' timed out.\n", - GNUNET_i2s(&th->peer)); -#endif - GNUNET_assert (0 == th->notify (th->notify_cls, 0, NULL)); - GNUNET_CORE_notify_transmit_ready_cancel (th); - if ((h->pending_head == th) && (h->cth != NULL)) /* Request hasn't been canceled yet! */ - { - GNUNET_CLIENT_notify_transmit_ready_cancel (h->cth); - h->cth = NULL; - trigger_next_request (h); - } - /* Otherwise this request timed out, but another is actually queued for sending, so don't try to send another! */ - return 0; + GNUNET_SCHEDULER_cancel (handle->reconnect_task); + handle->reconnect_task = GNUNET_SCHEDULER_NO_TASK; } - sm = (struct SendMessage *) buf; - sm->header.type = htons (GNUNET_MESSAGE_TYPE_CORE_SEND); - sm->priority = htonl (th->priority); - sm->deadline = GNUNET_TIME_absolute_hton (th->timeout); - sm->peer = th->peer; - notify = th->notify; - notify_cls = th->notify_cls; - GNUNET_CORE_notify_transmit_ready_cancel (th); - trigger_next_request (h); - size = GNUNET_MIN (size, - GNUNET_CONSTANTS_MAX_ENCRYPTED_MESSAGE_SIZE); - GNUNET_assert (size >= sizeof (struct SendMessage)); - dt = notify (notify_cls, size - sizeof (struct SendMessage), &sm[1]); - if (0 == dt) + if (handle->cth != NULL) { -#if DEBUG_CORE - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Size of clients message to peer %s is 0!\n", - GNUNET_i2s(&sm->peer)); -#endif - /* client decided to send nothing! */ - return 0; + GNUNET_CLIENT_notify_transmit_ready_cancel (handle->cth); + handle->cth = NULL; } -#if DEBUG_CORE - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Produced SEND message to core with %u bytes payload\n", - dt); -#endif - GNUNET_assert (dt >= sizeof (struct GNUNET_MessageHeader)); - if (dt + sizeof (struct SendMessage) >= GNUNET_SERVER_MAX_MESSAGE_SIZE) + if (handle->client != NULL) { - GNUNET_break (0); - return 0; + GNUNET_CLIENT_disconnect (handle->client, GNUNET_NO); + handle->client = NULL; } -#if DEBUG_CORE - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Preparing for P2P transmission of %u bytes to `%4s'.\n", - dt, - GNUNET_i2s(&sm->peer)); -#endif - sm->header.size = htons (dt + sizeof (struct SendMessage)); - GNUNET_assert (dt + sizeof (struct SendMessage) <= size); - return dt + sizeof (struct SendMessage); + while (NULL != (cm = handle->pending_head)) + { + GNUNET_CONTAINER_DLL_remove (handle->pending_head, + handle->pending_tail, + cm); + GNUNET_free (cm); + } + GNUNET_CONTAINER_multihashmap_iterate (handle->peers, + &disconnect_and_free_peer_entry, + handle); + GNUNET_CONTAINER_multihashmap_destroy (handle->peers); + GNUNET_break (handle->ready_peer_head == NULL); + GNUNET_free (handle); } @@ -926,61 +1229,489 @@ produce_send (void *cls, size_t size, void *buf) */ struct GNUNET_CORE_TransmitHandle * GNUNET_CORE_notify_transmit_ready (struct GNUNET_CORE_Handle *handle, - unsigned int priority, + uint32_t priority, struct GNUNET_TIME_Relative maxdelay, const struct GNUNET_PeerIdentity *target, size_t notify_size, GNUNET_CONNECTION_TransmitReadyNotify notify, void *notify_cls) { + struct PeerRecord *pr; struct GNUNET_CORE_TransmitHandle *th; + struct GNUNET_CORE_TransmitHandle *pos; + struct GNUNET_CORE_TransmitHandle *prev; + struct GNUNET_CORE_TransmitHandle *minp; + pr = GNUNET_CONTAINER_multihashmap_get (handle->peers, + &target->hashPubKey); + if (NULL == pr) + { + /* attempt to send to peer that is not connected */ + GNUNET_break (0); + return NULL; + } GNUNET_assert (notify_size + sizeof (struct SendMessage) < GNUNET_SERVER_MAX_MESSAGE_SIZE); th = GNUNET_malloc (sizeof (struct GNUNET_CORE_TransmitHandle)); - th->ch = handle; - GNUNET_CONTAINER_DLL_insert_after (handle->pending_head, - handle->pending_tail, - handle->pending_tail, - th); - th->get_message = &produce_send; - th->get_message_cls = th; - th->notify = notify; - th->notify_cls = notify_cls; - th->peer = *target; + th->peer = pr; + th->get_message = notify; + th->get_message_cls = notify_cls; th->timeout = GNUNET_TIME_relative_to_absolute (maxdelay); - th->timeout_task = GNUNET_SCHEDULER_add_delayed (maxdelay, - &timeout_request, th); th->priority = priority; - th->msize = sizeof (struct SendMessage) + notify_size; + th->msize = notify_size; + /* bound queue size */ + if (pr->queue_size == handle->queue_size) + { + /* find lowest-priority entry */ + minp = pr->pending_head; + prev = minp->next; + while (prev != NULL) + { + if (prev->priority < minp->priority) + minp = prev; + prev = prev->next; + } + if (minp == NULL) + { + GNUNET_break (handle->queue_size != 0); + GNUNET_break (pr->queue_size == 0); + return NULL; + } + if (priority <= minp->priority) + return NULL; /* priority too low */ + GNUNET_CONTAINER_DLL_remove (pr->pending_head, + pr->pending_tail, + minp); + pr->queue_size--; + GNUNET_assert (0 == + minp->get_message (minp->get_message_cls, + 0, NULL)); + GNUNET_free (minp); + } + + /* Order entries by deadline, but SKIP 'HEAD' if + we're in the 'ready_peer_*' DLL */ + pos = pr->pending_head; + if ( (pr->prev != NULL) || + (pr->next != NULL) || + (pr == handle->ready_peer_head) ) + { + GNUNET_assert (pos != NULL); + pos = pos->next; /* skip head */ + } + + /* insertion sort */ + prev = pos; + while ( (pos != NULL) && + (pos->timeout.abs_value < th->timeout.abs_value) ) + { + prev = pos; + pos = pos->next; + } + GNUNET_CONTAINER_DLL_insert_after (pr->pending_head, + pr->pending_tail, + prev, + th); + pr->queue_size++; /* was the request queue previously empty? */ - if ( (handle->pending_head == th) && - (handle->cth == NULL) ) - trigger_next_request (handle); + if (pr->pending_head == th) + request_next_transmission (pr); return th; } /** * Cancel the specified transmission-ready notification. - *s + * * @param th handle that was returned by "notify_transmit_ready". */ void GNUNET_CORE_notify_transmit_ready_cancel (struct GNUNET_CORE_TransmitHandle *th) { - struct GNUNET_CORE_Handle *h = th->ch; + struct PeerRecord *pr = th->peer; + struct GNUNET_CORE_Handle *h = pr->ch; + int was_head; - if (h->submitted == th) - h->submitted = NULL; - else - GNUNET_CONTAINER_DLL_remove (h->pending_head, - h->pending_tail, - th); - if (th->timeout_task != GNUNET_SCHEDULER_NO_TASK) - GNUNET_SCHEDULER_cancel (th->timeout_task); + was_head = (pr->pending_head == th); + GNUNET_CONTAINER_DLL_remove (pr->pending_head, + pr->pending_tail, + th); + if (th->cm != NULL) + { + /* we're currently in the control queue, remove */ + GNUNET_CONTAINER_DLL_remove (h->pending_head, + h->pending_tail, + th->cm); + GNUNET_free (th->cm); + } GNUNET_free (th); + if (was_head) + { + if ( (pr->prev != NULL) || + (pr->next != NULL) || + (pr == h->ready_peer_head) ) + { + /* the request that was 'approved' by core was + cancelled before it could be transmitted; remove + us from the 'ready' list */ + GNUNET_CONTAINER_DLL_remove (h->ready_peer_head, + h->ready_peer_tail, + pr); + } + request_next_transmission (pr); + } +} + + +/* ****************** GNUNET_CORE_peer_request_connect ******************** */ + +/** + * Handle for a request to the core to connect to + * a particular peer. Can be used to cancel the request + * (before the 'cont'inuation is called). + */ +struct GNUNET_CORE_PeerRequestHandle +{ + + /** + * Link to control message. + */ + struct ControlMessage *cm; + + /** + * Core handle used. + */ + struct GNUNET_CORE_Handle *h; + + /** + * Continuation to run when done. + */ + GNUNET_SCHEDULER_Task cont; + + /** + * Closure for 'cont'. + */ + void *cont_cls; + +}; + + + +/** + * Continuation called when the control message was transmitted. + * Calls the original continuation and frees the remaining + * resources. + * + * @param cls the 'struct GNUNET_CORE_PeerRequestHandle' + * @param tc scheduler context + */ +static void +peer_request_connect_cont (void *cls, + const struct GNUNET_SCHEDULER_TaskContext *tc) +{ + struct GNUNET_CORE_PeerRequestHandle *ret = cls; + + if (ret->cont != NULL) + ret->cont (ret->cont_cls, tc); + GNUNET_free (ret); +} + + +/** + * Request that the core should try to connect to a particular peer. + * Once the request has been transmitted to the core, the continuation + * function will be called. Note that this does NOT mean that a + * connection was successfully established -- it only means that the + * core will now try. Successful establishment of the connection + * will be signalled to the 'connects' callback argument of + * 'GNUNET_CORE_connect' only. If the core service does not respond + * to our connection attempt within the given time frame, 'cont' will + * be called with the TIMEOUT reason code. + * + * @param h core handle + * @param timeout how long to try to talk to core + * @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 + */ +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, + void *cont_cls) +{ + struct GNUNET_CORE_PeerRequestHandle *ret; + struct ControlMessage *cm; + struct ConnectMessage *msg; + + cm = GNUNET_malloc (sizeof (struct ControlMessage) + + sizeof (struct ConnectMessage)); + msg = (struct ConnectMessage*) &cm[1]; + msg->header.type = htons (GNUNET_MESSAGE_TYPE_CORE_REQUEST_CONNECT); + msg->header.size = htons (sizeof (struct ConnectMessage)); + 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); + ret = GNUNET_malloc (sizeof (struct GNUNET_CORE_PeerRequestHandle)); + ret->h = h; + ret->cm = cm; + ret->cont = cont; + ret->cont_cls = cont_cls; + cm->cont = &peer_request_connect_cont; + cm->cont_cls = ret; + if (h->pending_head == cm) + trigger_next_request (h); + return ret; +} + + +/** + * Cancel a pending request to connect to a particular peer. Must not + * be called after the 'cont' function was invoked. + * + * @param req request handle that was returned for the original request + */ +void +GNUNET_CORE_peer_request_connect_cancel (struct GNUNET_CORE_PeerRequestHandle *req) +{ + struct GNUNET_CORE_Handle *h = req->h; + struct ControlMessage *cm = req->cm; + + GNUNET_CONTAINER_DLL_remove (h->pending_head, + h->pending_tail, + cm); + GNUNET_free (cm); + GNUNET_free (req); +} + + +/* ****************** GNUNET_CORE_peer_change_preference ******************** */ + + +struct GNUNET_CORE_InformationRequestContext +{ + + /** + * Our connection to the service. + */ + 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. + */ + struct ControlMessage *cm; + + /** + * Link to peer record. + */ + struct PeerRecord *pr; +}; + + +/** + * CM was sent, remove link so we don't double-free. + * + * @param cls the 'struct GNUNET_CORE_InformationRequestContext' + * @param tc scheduler context + */ +static void +change_preference_send_continuation (void *cls, + const struct GNUNET_SCHEDULER_TaskContext *tc) +{ + struct GNUNET_CORE_InformationRequestContext *irc = cls; + + irc->cm = NULL; +} + + +/** + * Obtain statistics and/or change preferences for the given peer. + * + * @param h core handle + * @param peer identifies the peer + * @param timeout after how long should we give up (and call "info" with NULL + * for "peer" to signal an error)? + * @param bw_out set to the current bandwidth limit (sending) for this peer, + * caller should set "bw_out" to "-1" to avoid changing + * the current value; otherwise "bw_out" will be lowered to + * the specified value; passing a pointer to "0" can be used to force + * us to disconnect from the peer; "bw_out" might not increase + * as specified since the upper bound is generally + * determined by the other peer! + * @param amount reserve N bytes for receiving, negative + * amounts can be used to undo a (recent) reservation; + * @param preference increase incoming traffic share preference by this amount; + * in the absence of "amount" reservations, we use this + * preference value to assign proportional bandwidth shares + * to all connected peers + * @param info function to call with the resulting configuration information + * @param info_cls closure for info + * @return NULL on error + */ +struct GNUNET_CORE_InformationRequestContext * +GNUNET_CORE_peer_change_preference (struct GNUNET_CORE_Handle *h, + const struct GNUNET_PeerIdentity *peer, + struct GNUNET_TIME_Relative timeout, + struct GNUNET_BANDWIDTH_Value32NBO bw_out, + int32_t amount, + uint64_t preference, + GNUNET_CORE_PeerConfigurationInfoCallback info, + void *info_cls) +{ + struct GNUNET_CORE_InformationRequestContext *irc; + struct PeerRecord *pr; + struct RequestInfoMessage *rim; + struct ControlMessage *cm; + + pr = GNUNET_CONTAINER_multihashmap_get (h->peers, + &peer->hashPubKey); + if (NULL == pr) + { + /* attempt to change preference on peer that is not connected */ + GNUNET_break (0); + return NULL; + } + if (pr->pcic != NULL) + { + /* second change before first one is done */ + GNUNET_break (0); + return NULL; + } + irc = GNUNET_malloc (sizeof (struct GNUNET_CORE_InformationRequestContext)); + irc->h = h; + irc->info = info; + irc->info_cls = info_cls; + cm = GNUNET_malloc (sizeof (struct ControlMessage) + + sizeof (struct RequestInfoMessage)); + cm->cont = &change_preference_send_continuation; + cm->cont_cls = irc; + irc->cm = cm; + rim = (struct RequestInfoMessage*) &cm[1]; + rim->header.size = htons (sizeof (struct RequestInfoMessage)); + rim->header.type = htons (GNUNET_MESSAGE_TYPE_CORE_REQUEST_INFO); + rim->rim_id = htonl (pr->rim_id = h->rim_id_gen++); + rim->limit_outbound = bw_out; + rim->reserve_inbound = htonl (amount); + rim->preference_change = GNUNET_htonll(preference); + rim->peer = *peer; + GNUNET_CONTAINER_DLL_insert (h->pending_head, + h->pending_tail, + cm); + pr->pcic = info; + pr->pcic_cls = info_cls; + return irc; +} + + +/** + * Cancel request for getting information about a peer. + * Note that an eventual change in preference, trust or bandwidth + * assignment MAY have already been committed at the time, + * so cancelling a request is NOT sure to undo the original + * request. The original request may or may not still commit. + * The only thing cancellation ensures is that the callback + * from the original request will no longer be called. + * + * @param irc context returned by the original GNUNET_CORE_peer_get_info call + */ +void +GNUNET_CORE_peer_change_preference_cancel (struct GNUNET_CORE_InformationRequestContext *irc) +{ + struct GNUNET_CORE_Handle *h = irc->h; + struct PeerRecord *pr = irc->pr; + + if (irc->cm != NULL) + { + GNUNET_CONTAINER_DLL_remove (h->pending_head, + h->pending_tail, + irc->cm); + GNUNET_free (irc->cm); + } + pr->pcic = NULL; + pr->pcic_cls = NULL; + GNUNET_free (irc); +} + + +/* ********************* GNUNET_CORE_iterate_peers *********************** */ + +/** + * Context for 'iterate_peers' helper function. + */ +struct IterationContext +{ + /** + * Callback to call. + */ + GNUNET_CORE_ConnectEventHandler peer_cb; + + /** + * Closure for 'peer_cb'. + */ + void *cb_cls; +}; + + +/** + * Call callback for each peer. + * + * @param cls the 'struct IterationContext' + * @param hc peer identity, not used + * @param value the 'struct PeerRecord' + * @return GNUNET_YES (continue iteration) + */ +static int +iterate_peers (void *cls, + const GNUNET_HashCode *hc, + void *value) +{ + struct IterationContext *ic = cls; + struct PeerRecord *pr = value; + + ic->peer_cb (ic->cb_cls, + &pr->peer, + NULL /* FIXME: pass atsi? */); + return GNUNET_YES; +} + + +/** + * Obtain statistics and/or change preferences for the given peer. + * + * @param h handle to core + * @param peer_cb function to call with the peer information + * @param cb_cls closure for peer_cb + * @return GNUNET_OK if iterating, GNUNET_SYSERR on error + */ +int +GNUNET_CORE_iterate_peers (struct GNUNET_CORE_Handle *h, + GNUNET_CORE_ConnectEventHandler peer_cb, + void *cb_cls) +{ + struct IterationContext ic; + + ic.peer_cb = peer_cb; + ic.cb_cls = cb_cls; + GNUNET_CONTAINER_multihashmap_iterate (h->peers, + &iterate_peers, + &ic); + return GNUNET_OK; } diff --git a/src/core/core_api_iterate_peers.c b/src/core/core_api_iterate_peers.c deleted file mode 100644 index aeef67f88..000000000 --- a/src/core/core_api_iterate_peers.c +++ /dev/null @@ -1,169 +0,0 @@ -/* - This file is part of GNUnet. - (C) 2009, 2010 Christian Grothoff (and other contributing authors) - - GNUnet is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published - by the Free Software Foundation; either version 3, or (at your - option) any later version. - - GNUnet is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with GNUnet; see the file COPYING. If not, write to the - Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. -*/ - -/** - * @file core/core_api_iterate_peers.c - * @brief implementation of the peer_iterate function - * @author Christian Grothoff - * @author Nathan Evans - */ -#include "platform.h" -#include "gnunet_core_service.h" -#include "core.h" - - -struct GNUNET_CORE_RequestContext -{ - - /** - * Our connection to the service. - */ - struct GNUNET_CLIENT_Connection *client; - - /** - * Handle for transmitting a request. - */ - struct GNUNET_CLIENT_TransmitHandle *th; - - /** - * Function called with the peer. - */ - GNUNET_CORE_ConnectEventHandler peer_cb; - - /** - * Closure for peer_cb. - */ - void *cb_cls; - -}; - - -/** - * Receive reply from core service with information about a peer. - * - * @param cls our 'struct GNUNET_CORE_RequestContext *' - * @param msg NULL on error or last entry - */ -static void -receive_info (void *cls, - const struct GNUNET_MessageHeader *msg) -{ - struct GNUNET_CORE_RequestContext *request_context = cls; - const struct ConnectNotifyMessage *connect_message; - - - /* Handle last message or error case, disconnect and clean up */ - if ( (msg == NULL) || - ((ntohs (msg->type) == GNUNET_MESSAGE_TYPE_CORE_NOTIFY_CONNECT) && - (ntohs (msg->size) == sizeof (struct GNUNET_MessageHeader))) ) - { - if (request_context->peer_cb != NULL) - request_context->peer_cb (request_context->cb_cls, - NULL, GNUNET_TIME_relative_get_zero(), 0); - GNUNET_CLIENT_disconnect (request_context->client, GNUNET_NO); - GNUNET_free (request_context); - return; - } - - /* Handle incorrect message type or size, disconnect and clean up */ - if ( (ntohs (msg->type) != GNUNET_MESSAGE_TYPE_CORE_NOTIFY_CONNECT) || - (ntohs (msg->size) != sizeof (struct ConnectNotifyMessage)) ) - { - GNUNET_break (0); - if (request_context->peer_cb != NULL) - request_context->peer_cb (request_context->cb_cls, - NULL, GNUNET_TIME_relative_get_zero(), 0); - GNUNET_CLIENT_disconnect (request_context->client, GNUNET_NO); - GNUNET_free (request_context); - return; - } - - /* Normal case */ - connect_message = (const struct ConnectNotifyMessage *) msg; - if (request_context->peer_cb != NULL) - request_context->peer_cb (request_context->cb_cls, - &connect_message->peer, - GNUNET_TIME_relative_ntoh(connect_message->latency), - ntohl (connect_message->distance)); - - GNUNET_CLIENT_receive(request_context->client, &receive_info, request_context, GNUNET_TIME_relative_get_forever()); -} - -/** - * Function called to notify a client about the socket - * begin ready to queue more data. "buf" will be - * NULL and "size" zero if the socket was closed for - * writing in the meantime. - * - * @param cls closure - * @param size number of bytes available in buf - * @param buf where the callee should write the message - * @return number of bytes written to buf - */ -static size_t -transmit_request(void *cls, - size_t size, void *buf) -{ - struct GNUNET_MessageHeader *msg; - if ((size < sizeof(struct GNUNET_MessageHeader)) || (buf == NULL)) - return 0; - - msg = (struct GNUNET_MessageHeader *)buf; - msg->size = htons (sizeof (struct GNUNET_MessageHeader)); - msg->type = htons (GNUNET_MESSAGE_TYPE_CORE_ITERATE_PEERS); - return sizeof(struct GNUNET_MessageHeader); -} - -/** - * Obtain statistics and/or change preferences for the given peer. - * - * @param cfg configuration to use - * @param peer_cb function to call with the peer information - * @param cb_cls closure for peer_cb - * @return GNUNET_OK if iterating, GNUNET_SYSERR on error - */ -int -GNUNET_CORE_iterate_peers (const struct GNUNET_CONFIGURATION_Handle *cfg, - GNUNET_CORE_ConnectEventHandler peer_cb, - void *cb_cls) -{ - struct GNUNET_CORE_RequestContext *request_context; - struct GNUNET_CLIENT_Connection *client; - - client = GNUNET_CLIENT_connect ("core", cfg); - if (client == NULL) - return GNUNET_SYSERR; - request_context = GNUNET_malloc (sizeof (struct GNUNET_CORE_RequestContext)); - request_context->client = client; - request_context->peer_cb = peer_cb; - request_context->cb_cls = cb_cls; - - /*GNUNET_assert (GNUNET_OK == GNUNET_CLIENT_transmit_and_get_response (client, - &request_message, - GNUNET_TIME_relative_get_forever(), - GNUNET_YES, - &receive_info, - request_context));*/ - request_context->th = GNUNET_CLIENT_notify_transmit_ready(client, sizeof(struct GNUNET_MessageHeader), GNUNET_TIME_relative_get_forever(), GNUNET_YES, &transmit_request, NULL); - GNUNET_CLIENT_receive(client, &receive_info, request_context, GNUNET_TIME_relative_get_forever()); - return GNUNET_OK; -} - -/* end of core_api_iterate_peers.c */ diff --git a/src/core/core_api_peer_get_info.c b/src/core/core_api_peer_get_info.c deleted file mode 100644 index 1ca8d82af..000000000 --- a/src/core/core_api_peer_get_info.c +++ /dev/null @@ -1,175 +0,0 @@ -/* - This file is part of GNUnet. - (C) 2009, 2010 Christian Grothoff (and other contributing authors) - - GNUnet is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published - by the Free Software Foundation; either version 3, or (at your - option) any later version. - - GNUnet is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with GNUnet; see the file COPYING. If not, write to the - Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. -*/ - -/** - * @file core/core_api_peer_get_info.c - * @brief implementation of the peer_change_preference functions - * @author Christian Grothoff - */ -#include "platform.h" -#include "gnunet_core_service.h" -#include "core.h" - - -struct GNUNET_CORE_InformationRequestContext -{ - - /** - * Our connection to the service. - */ - struct GNUNET_CLIENT_Connection *client; - - /** - * Function to call with the information. - */ - GNUNET_CORE_PeerConfigurationInfoCallback info; - - /** - * Closure for info. - */ - void *info_cls; - -}; - - -/** - * Receive reply from core service with information about a peer. - * - * @param cls our 'struct GNUNET_CORE_InformationRequestContext *' - * @param msg NULL on error (i.e. timeout) - */ -static void -receive_info (void *cls, - const struct GNUNET_MessageHeader *msg) -{ - struct GNUNET_CORE_InformationRequestContext *irc = cls; - const struct ConfigurationInfoMessage *cim; - static struct GNUNET_BANDWIDTH_Value32NBO zbw; /* zero bandwidth */ - - if (msg == NULL) - { - if (irc->info != NULL) - irc->info (irc->info_cls, - NULL, zbw, zbw, 0, 0); - GNUNET_CLIENT_disconnect (irc->client, GNUNET_NO); - GNUNET_free (irc); - return; - } - if ( (ntohs (msg->type) != GNUNET_MESSAGE_TYPE_CORE_CONFIGURATION_INFO) || - (ntohs (msg->size) != sizeof (struct ConfigurationInfoMessage)) ) - { - GNUNET_break (0); - if (irc->info != NULL) - irc->info (irc->info_cls, - NULL, zbw, zbw, 0, 0); - GNUNET_CLIENT_disconnect (irc->client, GNUNET_NO); - GNUNET_free (irc); - return; - } - cim = (const struct ConfigurationInfoMessage*) msg; - if (irc->info != NULL) - irc->info (irc->info_cls, - &cim->peer, - cim->bw_in, - cim->bw_out, - ntohl (cim->reserved_amount), - GNUNET_ntohll (cim->preference)); - GNUNET_CLIENT_disconnect (irc->client, GNUNET_NO); - GNUNET_free (irc); -} - - -/** - * Obtain statistics and/or change preferences for the given peer. - * - * @param cfg configuration to use - * @param peer identifies the peer - * @param timeout after how long should we give up (and call "info" with NULL - * for "peer" to signal an error)? - * @param bw_out set to the current bandwidth limit (sending) for this peer, - * caller should set "bw_out" to "-1" to avoid changing - * the current value; otherwise "bw_out" will be lowered to - * the specified value; passing a pointer to "0" can be used to force - * us to disconnect from the peer; "bw_out" might not increase - * as specified since the upper bound is generally - * determined by the other peer! - * @param amount reserve N bytes for receiving, negative - * amounts can be used to undo a (recent) reservation; - * @param preference increase incoming traffic share preference by this amount; - * in the absence of "amount" reservations, we use this - * preference value to assign proportional bandwidth shares - * to all connected peers - * @param info function to call with the resulting configuration information - * @param info_cls closure for info - * @return NULL on error - */ -struct GNUNET_CORE_InformationRequestContext * -GNUNET_CORE_peer_change_preference (const struct GNUNET_CONFIGURATION_Handle *cfg, - const struct GNUNET_PeerIdentity *peer, - struct GNUNET_TIME_Relative timeout, - struct GNUNET_BANDWIDTH_Value32NBO bw_out, - int32_t amount, - uint64_t preference, - GNUNET_CORE_PeerConfigurationInfoCallback info, - void *info_cls) -{ - struct GNUNET_CORE_InformationRequestContext *irc; - struct RequestInfoMessage rim; - struct GNUNET_CLIENT_Connection *client; - int retry; - - client = GNUNET_CLIENT_connect ("core", cfg); - if (client == NULL) - return NULL; - irc = GNUNET_malloc (sizeof (struct GNUNET_CORE_InformationRequestContext)); - irc->client = client; - irc->info = info; - irc->info_cls = info_cls; - rim.header.size = htons (sizeof (struct RequestInfoMessage)); - rim.header.type = htons (GNUNET_MESSAGE_TYPE_CORE_REQUEST_INFO); - rim.reserved = htonl (0); - rim.limit_outbound = bw_out; - rim.reserve_inbound = htonl (amount); - rim.preference_change = GNUNET_htonll(preference); - rim.peer = *peer; - retry = ( (amount == 0) && (preference == 0) ) ? GNUNET_YES : GNUNET_NO; - GNUNET_assert (GNUNET_OK == GNUNET_CLIENT_transmit_and_get_response (client, - &rim.header, - timeout, - retry, - &receive_info, - irc)); - return irc; -} - - -/** - * Cancel request for getting information about a peer. - * - * @param irc context returned by the original GNUNET_CORE_peer_get_info call - */ -void -GNUNET_CORE_peer_change_preference_cancel (struct GNUNET_CORE_InformationRequestContext *irc) -{ - GNUNET_CLIENT_disconnect (irc->client, GNUNET_NO); - GNUNET_free (irc); -} - -/* end of core_api_peer_get_info.c */ diff --git a/src/core/core_api_peer_request.c b/src/core/core_api_peer_request.c deleted file mode 100644 index 0f13f15f9..000000000 --- a/src/core/core_api_peer_request.c +++ /dev/null @@ -1,179 +0,0 @@ -/* - This file is part of GNUnet. - (C) 2009, 2010 Christian Grothoff (and other contributing authors) - - GNUnet is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published - by the Free Software Foundation; either version 3, or (at your - option) any later version. - - GNUnet is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with GNUnet; see the file COPYING. If not, write to the - Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. -*/ - -/** - * @file core/core_api_peer_request.c - * @brief implementation of the peer_request functions - * @author Christian Grothoff - */ -#include "platform.h" -#include "gnunet_core_service.h" -#include "core.h" - - -/** - * Handle for a request to the core to connect to - * a particular peer. Can be used to cancel the request - * (before the 'cont'inuation is called). - */ -struct GNUNET_CORE_PeerRequestHandle -{ - - /** - * Our connection to the service. - */ - struct GNUNET_CLIENT_Connection *client; - - - /** - * Function to call once done. - */ - GNUNET_SCHEDULER_Task cont; - - /** - * Closure for 'cont'. - */ - void *cont_cls; - - /** - * When to time out. - */ - struct GNUNET_TIME_Absolute timeout; - - /** - * Identity of the peer to connect to. - */ - struct GNUNET_PeerIdentity peer; - - /** - * Message type to use. - */ - uint16_t type; -}; - - -/** - * Transmit the request to the core service. - * - * @param cls our 'struct GNUNET_CORE_PeerRequestHandle' - * @param size number of bytes available in buf - * @param buf where the callee should write the message - * @return number of bytes written to buf - */ -static size_t -send_request (void *cls, - size_t size, - void *buf) -{ - struct GNUNET_CORE_PeerRequestHandle * prh = cls; - struct ConnectMessage msg; - - if (buf == NULL) - { - if (prh->cont != NULL) - GNUNET_SCHEDULER_add_continuation (prh->cont, - prh->cont_cls, - GNUNET_SCHEDULER_REASON_TIMEOUT); - GNUNET_CLIENT_disconnect (prh->client, GNUNET_NO); - GNUNET_free (prh); - return 0; - } - GNUNET_assert (size >= sizeof (struct ConnectMessage)); - msg.header.type = htons (prh->type); - msg.header.size = htons (sizeof (struct ConnectMessage)); - msg.reserved = htonl (0); - msg.timeout = GNUNET_TIME_relative_hton (GNUNET_TIME_absolute_get_remaining (prh->timeout)); - msg.peer = prh->peer; - memcpy (buf, &msg, sizeof (msg)); - if (prh->cont != NULL) - { - GNUNET_SCHEDULER_add_continuation (prh->cont, - prh->cont_cls, - GNUNET_SCHEDULER_REASON_PREREQ_DONE); - } - GNUNET_CLIENT_disconnect (prh->client, GNUNET_YES); - GNUNET_free (prh); - return sizeof (msg); -} - - -/** - * Request that the core should try to connect to a particular peer. - * Once the request has been transmitted to the core, the continuation - * function will be called. Note that this does NOT mean that a - * connection was successfully established -- it only means that the - * core will now try. Successful establishment of the connection - * will be signalled to the 'connects' callback argument of - * 'GNUNET_CORE_connect' only. If the core service does not respond - * to our connection attempt within the given time frame, 'cont' will - * be called with the TIMEOUT reason code. - * - * @param cfg configuration to use - * @param timeout how long to try to talk to core - * @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 - */ -struct GNUNET_CORE_PeerRequestHandle * -GNUNET_CORE_peer_request_connect (const struct GNUNET_CONFIGURATION_Handle *cfg, - struct GNUNET_TIME_Relative timeout, - const struct GNUNET_PeerIdentity * peer, - GNUNET_SCHEDULER_Task cont, - void *cont_cls) -{ - struct GNUNET_CORE_PeerRequestHandle *ret; - struct GNUNET_CLIENT_Connection *client; - - client = GNUNET_CLIENT_connect ("core", cfg); - if (client == NULL) - return NULL; - ret = GNUNET_malloc (sizeof (struct GNUNET_CORE_PeerRequestHandle)); - ret->client = client; - ret->cont = cont; - ret->cont_cls = cont_cls; - ret->peer = *peer; - ret->type = GNUNET_MESSAGE_TYPE_CORE_REQUEST_CONNECT; - ret->timeout = GNUNET_TIME_relative_to_absolute (timeout); - GNUNET_CLIENT_notify_transmit_ready (client, - sizeof (struct ConnectMessage), - timeout, - GNUNET_YES, - &send_request, - ret); - return ret; -} - - -/** - * Cancel a pending request to connect to a particular peer. Must not - * be called after the 'cont' function was invoked. - * - * @param req request handle that was returned for the original request - */ -void -GNUNET_CORE_peer_request_connect_cancel (struct GNUNET_CORE_PeerRequestHandle *req) -{ - GNUNET_CLIENT_disconnect (req->client, GNUNET_NO); - GNUNET_free (req); -} - - -/* end of core_api_peer_request.c */ diff --git a/src/core/gnunet-service-core.c b/src/core/gnunet-service-core.c index c1ebdb9df..034f80060 100644 --- a/src/core/gnunet-service-core.c +++ b/src/core/gnunet-service-core.c @@ -391,6 +391,15 @@ struct MessageEntry }; +/** + * Record kept for each request for transmission issued by a + * client that is still pending. + */ +struct ClientActiveRequest; + +/** + * Data kept per neighbouring peer. + */ struct Neighbour { /** @@ -415,6 +424,18 @@ struct Neighbour */ struct MessageEntry *encrypted_tail; + /** + * Head of list of requests from clients for transmission to + * this peer. + */ + struct ClientActiveRequest *active_client_request_head; + + /** + * Tail of list of requests from clients for transmission to + * this peer. + */ + struct ClientActiveRequest *active_client_request_tail; + /** * Handle for pending requests for transmission to this peer * with the transport service. NULL if no request is pending. @@ -516,11 +537,6 @@ struct Neighbour */ struct GNUNET_TIME_Absolute last_activity; - /** - * Last latency observed from this peer. - */ - struct GNUNET_TIME_Relative last_latency; - /** * At what frequency are we currently re-trying SET_KEY messages? */ @@ -587,11 +603,6 @@ struct Neighbour */ uint32_t ping_challenge; - /** - * What was the last distance to this peer as reported by the transports? - */ - uint32_t last_distance; - /** * What is our connection status? */ @@ -627,6 +638,12 @@ struct Client */ const uint16_t *types; + /** + * Map of peer identities to active transmission requests of this + * client to the peer (of type 'struct ClientActiveRequest'). + */ + struct GNUNET_CONTAINER_MultiHashMap *requests; + /** * Options for messages this client cares about, * see GNUNET_CORE_OPTION_ values. @@ -642,6 +659,59 @@ struct Client }; +/** + * Record kept for each request for transmission issued by a + * client that is still pending. + */ +struct ClientActiveRequest +{ + + /** + * Active requests are kept in a doubly-linked list of + * the respective target peer. + */ + struct ClientActiveRequest *next; + + /** + * Active requests are kept in a doubly-linked list of + * the respective target peer. + */ + struct ClientActiveRequest *prev; + + /** + * Handle to the client. + */ + struct Client *client; + + /** + * By what time would the client want to see this message out? + */ + struct GNUNET_TIME_Absolute deadline; + + /** + * How important is this request. + */ + uint32_t priority; + + /** + * How many more requests does this client have? + */ + uint32_t queue_size; + + /** + * How many bytes does the client intend to send? + */ + uint16_t msize; + + /** + * Unique request ID (in big endian). + */ + uint16_t smr_id; + +}; + + + /** * Our public key. */ @@ -917,8 +987,6 @@ handle_peer_status_change (struct Neighbour *n) #endif psnm.header.size = htons (sizeof (struct PeerStatusNotifyMessage)); psnm.header.type = htons (GNUNET_MESSAGE_TYPE_CORE_NOTIFY_STATUS_CHANGE); - psnm.distance = htonl (n->last_distance); - psnm.latency = GNUNET_TIME_relative_hton (n->last_latency); psnm.timeout = GNUNET_TIME_absolute_hton (GNUNET_TIME_absolute_add (n->last_activity, GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT)); psnm.bandwidth_in = n->bw_in; @@ -933,46 +1001,127 @@ handle_peer_status_change (struct Neighbour *n) GNUNET_NO); } + /** - * Handle CORE_ITERATE_PEERS request. + * Go over our message queue and if it is not too long, go + * over the pending requests from clients for this + * neighbour and send some clients a 'READY' notification. + * + * @param n which peer to process */ static void -handle_client_iterate_peers (void *cls, - struct GNUNET_SERVER_Client *client, - const struct GNUNET_MessageHeader *message) +schedule_peer_messages (struct Neighbour *n) { - struct Neighbour *n; - struct ConnectNotifyMessage cnm; - struct GNUNET_MessageHeader done_msg; - struct GNUNET_SERVER_TransmitContext *tc; - - /* notify new client about existing neighbours */ - cnm.header.size = htons (sizeof (struct ConnectNotifyMessage)); - cnm.header.type = htons (GNUNET_MESSAGE_TYPE_CORE_NOTIFY_CONNECT); - done_msg.size = htons (sizeof (struct GNUNET_MessageHeader)); - done_msg.type = htons (GNUNET_MESSAGE_TYPE_CORE_NOTIFY_CONNECT); - tc = GNUNET_SERVER_transmit_context_create (client); - n = neighbours; - while (n != NULL) + struct SendMessageReady smr; + struct ClientActiveRequest *car; + struct ClientActiveRequest *pos; + struct Client *c; + struct MessageEntry *mqe; + unsigned int queue_size; + + /* check if neighbour queue is empty enough! */ + queue_size = 0; + mqe = n->messages; + while (mqe != NULL) { - if (n->status == PEER_STATE_KEY_CONFIRMED) - { -#if DEBUG_CORE_CLIENT - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Sending `%s' message to client.\n", "NOTIFY_CONNECT"); -#endif - cnm.distance = htonl (n->last_distance); - cnm.latency = GNUNET_TIME_relative_hton (n->last_latency); - cnm.peer = n->peer; - GNUNET_SERVER_transmit_context_append_message (tc, &cnm.header); - /*send_to_client (c, &cnm.header, GNUNET_NO);*/ - } - n = n->next; + queue_size++; + mqe = mqe->next; + } + if (queue_size >= MAX_PEER_QUEUE_SIZE) + return; /* queue still full */ + /* find highest priority request */ + pos = n->active_client_request_head; + car = NULL; + while (pos != NULL) + { + if ( (car == NULL) || + (pos->priority > car->priority) ) + car = pos; + pos = pos->next; } + if (car == NULL) + return; /* no pending requests */ + c = car->client; + GNUNET_CONTAINER_DLL_remove (n->active_client_request_head, + n->active_client_request_tail, + car); + GNUNET_CONTAINER_multihashmap_remove (c->requests, + &n->peer.hashPubKey, + car); + smr.header.size = htons (sizeof (struct SendMessageReady)); + smr.header.type = htons (GNUNET_MESSAGE_TYPE_CORE_SEND_READY); + smr.size = htons (car->msize); + smr.smr_id = car->smr_id; + smr.peer = n->peer; + send_to_client (c, &smr.header, GNUNET_NO); + GNUNET_free (car); +} - GNUNET_SERVER_transmit_context_append_message (tc, &done_msg); - GNUNET_SERVER_transmit_context_run (tc, - GNUNET_TIME_UNIT_FOREVER_REL); + +/** + * Handle CORE_SEND_REQUEST message. + */ +static void +handle_client_send_request (void *cls, + struct GNUNET_SERVER_Client *client, + const struct GNUNET_MessageHeader *message) +{ + const struct SendMessageRequest *req; + struct Neighbour *n; + struct Client *c; + struct ClientActiveRequest *car; + + req = (const struct SendMessageRequest*) message; + n = find_neighbour (&req->peer); + if ( (n == NULL) || + (GNUNET_YES != n->is_connected) ) + { + /* neighbour must have disconnected since request was issued, + ignore (client will realize it once it processes the + disconnect notification) */ + GNUNET_STATISTICS_update (stats, + gettext_noop ("# send requests dropped (disconnected)"), + 1, + GNUNET_NO); + GNUNET_SERVER_receive_done (client, GNUNET_OK); + return; + } + c = clients; + while ( (c != NULL) && + (c->client_handle != client) ) + c = c->next; + if (c == NULL) + { + /* client did not send INIT first! */ + GNUNET_break (0); + GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); + return; + } + if (c->requests == NULL) + c->requests = GNUNET_CONTAINER_multihashmap_create (16); + car = GNUNET_CONTAINER_multihashmap_get (c->requests, + &req->peer.hashPubKey); + if (car == NULL) + { + /* create new entry */ + car = GNUNET_malloc (sizeof (struct ClientActiveRequest)); + GNUNET_assert (GNUNET_OK == + GNUNET_CONTAINER_multihashmap_put (c->requests, + &req->peer.hashPubKey, + car, + GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST)); + GNUNET_CONTAINER_DLL_insert (n->active_client_request_head, + n->active_client_request_tail, + car); + car->client = c; + } + car->deadline = GNUNET_TIME_absolute_ntoh (req->deadline); + car->priority = ntohl (req->priority); + car->queue_size = ntohl (req->queue_size); + car->msize = ntohs (req->size); + car->smr_id = req->smr_id; + schedule_peer_messages (n); + GNUNET_SERVER_receive_done (client, GNUNET_OK); } @@ -1064,8 +1213,6 @@ handle_client_init (void *cls, GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending `%s' message to client.\n", "NOTIFY_CONNECT"); #endif - cnm.distance = htonl (n->last_distance); - cnm.latency = GNUNET_TIME_relative_hton (n->last_latency); cnm.peer = n->peer; send_to_client (c, &cnm.header, GNUNET_NO); } @@ -1076,6 +1223,33 @@ handle_client_init (void *cls, } +/** + * Free client request records. + * + * @param cls NULL + * @param key identity of peer for which this is an active request + * @param value the 'struct ClientActiveRequest' to free + * @return GNUNET_YES (continue iteration) + */ +static int +destroy_active_client_request (void *cls, + const GNUNET_HashCode *key, + void *value) +{ + struct ClientActiveRequest *car = cls; + struct Neighbour *n; + struct GNUNET_PeerIdentity peer; + + peer.hashPubKey = *key; + n = find_neighbour (&peer); + GNUNET_CONTAINER_DLL_remove (n->active_client_request_head, + n->active_client_request_tail, + car); + GNUNET_free (car); + return GNUNET_YES; +} + + /** * A client disconnected, clean up. * @@ -1100,18 +1274,27 @@ handle_client_disconnect (void *cls, struct GNUNET_SERVER_Client *client) while (pos != NULL) { if (client == pos->client_handle) - { - if (prev == NULL) - clients = pos->next; - else - prev->next = pos->next; - GNUNET_free (pos); - return; - } + break; prev = pos; pos = pos->next; } - /* client never sent INIT */ + if (pos == NULL) + { + /* client never sent INIT */ + return; + } + if (prev == NULL) + clients = pos->next; + else + prev->next = pos->next; + if (pos->requests != NULL) + { + GNUNET_CONTAINER_multihashmap_iterate (pos->requests, + &destroy_active_client_request, + NULL); + GNUNET_CONTAINER_multihashmap_destroy (pos->requests); + } + GNUNET_free (pos); } @@ -1192,7 +1375,7 @@ handle_client_request_info (void *cls, (int) got_reserv); #endif cim.reserved_amount = htonl (got_reserv); - cim.bw_in = n->bw_in; + cim.rim_id = rcm->rim_id; cim.bw_out = n->bw_out; cim.preference = n->current_preference; } @@ -1221,6 +1404,7 @@ static void free_neighbour (struct Neighbour *n) { struct MessageEntry *m; + struct ClientActiveRequest *car; #if DEBUG_CORE GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, @@ -1249,6 +1433,16 @@ free_neighbour (struct Neighbour *n) m); GNUNET_free (m); } + while (NULL != (car = n->active_client_request_head)) + { + GNUNET_CONTAINER_DLL_remove (n->active_client_request_head, + n->active_client_request_tail, + car); + GNUNET_CONTAINER_multihashmap_remove (car->client->requests, + &n->peer.hashPubKey, + car); + GNUNET_free (car); + } if (NULL != n->th) { GNUNET_TRANSPORT_notify_transmit_ready_cancel (n->th); @@ -1894,8 +2088,6 @@ batch_message (struct Neighbour *n, return 0; } ntm->header.type = htons (GNUNET_MESSAGE_TYPE_CORE_NOTIFY_OUTBOUND); - ntm->distance = htonl (n->last_distance); - ntm->latency = GNUNET_TIME_relative_hton (n->last_latency); ntm->peer = n->peer; pos = n->messages; prev = NULL; @@ -1985,7 +2177,9 @@ discard_expired_messages (struct Neighbour *n) struct MessageEntry *pos; struct GNUNET_TIME_Absolute now; struct GNUNET_TIME_Relative delta; + int disc; + disc = GNUNET_NO; now = GNUNET_TIME_absolute_get (); prev = NULL; pos = n->messages; @@ -2004,12 +2198,19 @@ discard_expired_messages (struct Neighbour *n) n->messages = next; else prev->next = next; + GNUNET_STATISTICS_update (stats, + gettext_noop ("# messages discarded (expired prior to transmission)"), + 1, + GNUNET_NO); + disc = GNUNET_YES; GNUNET_free (pos); } else prev = pos; pos = next; } + if (GNUNET_YES == disc) + schedule_peer_messages (n); } @@ -2217,6 +2418,7 @@ process_plaintext_neighbour_queue (struct Neighbour *n) n->encrypted_tail, me); process_encrypted_neighbour_queue (n); + schedule_peer_messages (n); } @@ -2342,8 +2544,15 @@ handle_client_send (void *cls, (unsigned int) msize, GNUNET_i2s (&sm->peer)); #endif - /* bound queue size */ discard_expired_messages (n); + /* bound queue size */ + /* NOTE: this entire block to bound the queue size should be + obsolete with the new client-request code and the + 'schedule_peer_messages' mechanism; we still have this code in + here for now as a sanity check for the new mechanmism; + ultimately, we should probably simply reject SEND messages that + are not 'approved' (or provide a new core API for very unreliable + delivery that always sends with priority 0). Food for thought. */ min_prio = UINT32_MAX; min_prio_entry = NULL; min_prio_prev = NULL; @@ -2367,7 +2576,8 @@ handle_client_send (void *cls, /* queue full */ if (ntohl(sm->priority) <= min_prio) { - /* discard new entry */ + /* discard new entry; this should no longer happen! */ + GNUNET_break (0); #if DEBUG_CORE GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Queue full (%u/%u), discarding new request (%u bytes of type %u)\n", @@ -2376,7 +2586,9 @@ handle_client_send (void *cls, (unsigned int) msize, (unsigned int) ntohs (message->type)); #endif - GNUNET_STATISTICS_update (stats, gettext_noop ("# discarded CORE_SEND requests"), 1, GNUNET_NO); + GNUNET_STATISTICS_update (stats, + gettext_noop ("# discarded CORE_SEND requests"), + 1, GNUNET_NO); if (client != NULL) GNUNET_SERVER_receive_done (client, GNUNET_OK); @@ -3087,8 +3299,6 @@ handle_pong (struct Neighbour *n, } cnm.header.size = htons (sizeof (struct ConnectNotifyMessage)); cnm.header.type = htons (GNUNET_MESSAGE_TYPE_CORE_NOTIFY_CONNECT); - cnm.distance = htonl (n->last_distance); - cnm.latency = GNUNET_TIME_relative_hton (n->last_latency); cnm.peer = n->peer; send_to_all_clients (&cnm.header, GNUNET_YES, GNUNET_CORE_OPTION_SEND_CONNECT); process_encrypted_neighbour_queue (n); @@ -3308,8 +3518,6 @@ send_p2p_message_to_client (struct Neighbour *sender, ntm = (struct NotifyTrafficMessage *) buf; ntm->header.size = htons (msize + sizeof (struct NotifyTrafficMessage)); ntm->header.type = htons (GNUNET_MESSAGE_TYPE_CORE_NOTIFY_INBOUND); - ntm->distance = htonl (sender->last_distance); - ntm->latency = GNUNET_TIME_relative_hton (sender->last_latency); ntm->peer = sender->peer; memcpy (&ntm[1], m, msize); send_to_client (client, &ntm->header, GNUNET_YES); @@ -3602,9 +3810,7 @@ handle_transport_receive (void *cls, n = find_neighbour (peer); if (n == NULL) n = create_neighbour (peer); - changed = (latency.rel_value != n->last_latency.rel_value) || (distance != n->last_distance); - n->last_latency = latency; - n->last_distance = distance; + changed = GNUNET_YES; /* FIXME... */ up = (n->status == PEER_STATE_KEY_CONFIRMED); type = ntohs (message->type); size = ntohs (message->size); @@ -3832,8 +4038,6 @@ handle_transport_notify_connect (void *cls, 1, GNUNET_NO); n->is_connected = GNUNET_YES; - n->last_latency = latency; - n->last_distance = distance; GNUNET_BANDWIDTH_tracker_init (&n->available_send_window, n->bw_out, MAX_WINDOW_TIME_S); @@ -3868,6 +4072,7 @@ handle_transport_notify_disconnect (void *cls, { struct DisconnectNotifyMessage cnm; struct Neighbour *n; + struct ClientActiveRequest *car; struct GNUNET_TIME_Relative left; #if DEBUG_CORE @@ -3890,6 +4095,17 @@ handle_transport_notify_disconnect (void *cls, send_to_all_clients (&cnm.header, GNUNET_YES, GNUNET_CORE_OPTION_SEND_DISCONNECT); } n->is_connected = GNUNET_NO; + while (NULL != (car = n->active_client_request_head)) + { + GNUNET_CONTAINER_DLL_remove (n->active_client_request_head, + n->active_client_request_tail, + car); + GNUNET_CONTAINER_multihashmap_remove (car->client->requests, + &n->peer.hashPubKey, + car); + GNUNET_free (car); + } + GNUNET_STATISTICS_update (stats, gettext_noop ("# peers connected (transport)"), -1, @@ -3964,9 +4180,9 @@ run (void *cls, {&handle_client_request_info, NULL, GNUNET_MESSAGE_TYPE_CORE_REQUEST_INFO, sizeof (struct RequestInfoMessage)}, - {&handle_client_iterate_peers, NULL, - GNUNET_MESSAGE_TYPE_CORE_ITERATE_PEERS, - sizeof (struct GNUNET_MessageHeader)}, + {&handle_client_send_request, NULL, + GNUNET_MESSAGE_TYPE_CORE_SEND_REQUEST, + sizeof (struct SendMessageRequest)}, {&handle_client_send, NULL, GNUNET_MESSAGE_TYPE_CORE_SEND, 0}, {&handle_client_request_connect, NULL, diff --git a/src/core/test_core_api.c b/src/core/test_core_api.c index 129184587..b41d30450 100644 --- a/src/core/test_core_api.c +++ b/src/core/test_core_api.c @@ -38,11 +38,6 @@ #define START_ARM GNUNET_YES -/** - * How long until we give up on transmitting the message? - */ -#define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 60) - #define MTYPE 12345 struct PeerContext @@ -103,8 +98,7 @@ terminate_task_error (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) static void connect_notify (void *cls, const struct GNUNET_PeerIdentity *peer, - struct GNUNET_TIME_Relative latency, - uint32_t distance) + const struct GNUNET_TRANSPORT_ATS_Information *atsi) { struct PeerContext *pc = cls; GNUNET_assert (pc->connect_status == 0); @@ -130,8 +124,7 @@ static int inbound_notify (void *cls, const struct GNUNET_PeerIdentity *other, const struct GNUNET_MessageHeader *message, - struct GNUNET_TIME_Relative latency, - uint32_t distance) + const struct GNUNET_TRANSPORT_ATS_Information *atsi) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Core provides inbound data from `%4s'.\n", GNUNET_i2s (other)); @@ -143,8 +136,7 @@ static int outbound_notify (void *cls, const struct GNUNET_PeerIdentity *other, const struct GNUNET_MessageHeader *message, - struct GNUNET_TIME_Relative latency, - uint32_t distance) + const struct GNUNET_TRANSPORT_ATS_Information *atsi) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Core notifies about outbound data for `%4s'.\n", @@ -160,8 +152,7 @@ static int process_mtype (void *cls, const struct GNUNET_PeerIdentity *peer, const struct GNUNET_MessageHeader *message, - struct GNUNET_TIME_Relative latency, - uint32_t distance) + const struct GNUNET_TRANSPORT_ATS_Information *atsi) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Receiving message from `%4s'.\n", GNUNET_i2s (peer)); @@ -220,7 +211,6 @@ init_notify (void *cls, OKPP; /* connect p2 */ GNUNET_CORE_connect (p2.cfg, 1, - TIMEOUT, &p2, &init_notify, &connect_notify, @@ -311,7 +301,6 @@ run (void *cls, setup_peer (&p1, "test_core_api_peer1.conf"); setup_peer (&p2, "test_core_api_peer2.conf"); GNUNET_CORE_connect (p1.cfg, 1, - TIMEOUT, &p1, &init_notify, &connect_notify, diff --git a/src/core/test_core_api_reliability.c b/src/core/test_core_api_reliability.c index f22a9022e..14b69b80e 100644 --- a/src/core/test_core_api_reliability.c +++ b/src/core/test_core_api_reliability.c @@ -148,8 +148,7 @@ terminate_task_error (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) static void connect_notify (void *cls, const struct GNUNET_PeerIdentity *peer, - struct GNUNET_TIME_Relative latency, - uint32_t distance) + const struct GNUNET_TRANSPORT_ATS_Information *atsi) { struct PeerContext *pc = cls; GNUNET_assert (pc->connect_status == 0); @@ -175,8 +174,7 @@ static int inbound_notify (void *cls, const struct GNUNET_PeerIdentity *other, const struct GNUNET_MessageHeader *message, - struct GNUNET_TIME_Relative latency, - uint32_t distance) + const struct GNUNET_TRANSPORT_ATS_Information *atsi) { #if VERBOSE GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, @@ -190,8 +188,7 @@ static int outbound_notify (void *cls, const struct GNUNET_PeerIdentity *other, const struct GNUNET_MessageHeader *message, - struct GNUNET_TIME_Relative latency, - uint32_t distance) + const struct GNUNET_TRANSPORT_ATS_Information *atsi) { #if VERBOSE GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, @@ -215,8 +212,7 @@ static int process_mtype (void *cls, const struct GNUNET_PeerIdentity *peer, const struct GNUNET_MessageHeader *message, - struct GNUNET_TIME_Relative latency, - uint32_t distance) + const struct GNUNET_TRANSPORT_ATS_Information *atsi) { static int n; unsigned int s; @@ -366,7 +362,6 @@ init_notify (void *cls, OKPP; /* connect p2 */ GNUNET_CORE_connect (p2.cfg, 1, - TIMEOUT, &p2, &init_notify, &connect_notify, @@ -456,7 +451,6 @@ run (void *cls, setup_peer (&p1, "test_core_api_peer1.conf"); setup_peer (&p2, "test_core_api_peer2.conf"); GNUNET_CORE_connect (p1.cfg, 1, - TIMEOUT, &p1, &init_notify, &connect_notify, diff --git a/src/core/test_core_api_start_only.c b/src/core/test_core_api_start_only.c index e39179196..6c042a2b2 100644 --- a/src/core/test_core_api_start_only.c +++ b/src/core/test_core_api_start_only.c @@ -35,12 +35,6 @@ #define START_ARM GNUNET_YES - -/** - * How long until we give up on transmitting the message? - */ -#define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 120) - #define MTYPE 12345 struct PeerContext @@ -71,8 +65,7 @@ static int ok; static void connect_notify (void *cls, const struct GNUNET_PeerIdentity *peer, - struct GNUNET_TIME_Relative latency, - uint32_t distance) + const struct GNUNET_TRANSPORT_ATS_Information *atsi) { } @@ -88,8 +81,7 @@ static int inbound_notify (void *cls, const struct GNUNET_PeerIdentity *other, const struct GNUNET_MessageHeader *message, - struct GNUNET_TIME_Relative latency, - uint32_t distance) + const struct GNUNET_TRANSPORT_ATS_Information *atsi) { return GNUNET_OK; } @@ -99,8 +91,7 @@ static int outbound_notify (void *cls, const struct GNUNET_PeerIdentity *other, const struct GNUNET_MessageHeader *message, - struct GNUNET_TIME_Relative latency, - uint32_t distance) + const struct GNUNET_TRANSPORT_ATS_Information *atsi) { return GNUNET_OK; } @@ -126,7 +117,6 @@ init_notify (void *cls, { /* connect p2 */ GNUNET_CORE_connect (p2.cfg, 1, - TIMEOUT, &p2, &init_notify, &connect_notify, @@ -173,7 +163,6 @@ run (void *cls, setup_peer (&p1, "test_core_api_peer1.conf"); setup_peer (&p2, "test_core_api_peer2.conf"); GNUNET_CORE_connect (p1.cfg, 1, - TIMEOUT, &p1, &init_notify, &connect_notify, diff --git a/src/core/test_core_quota_compliance.c b/src/core/test_core_quota_compliance.c index 5a3e3dc14..9d231c4e0 100644 --- a/src/core/test_core_quota_compliance.c +++ b/src/core/test_core_quota_compliance.c @@ -191,8 +191,7 @@ static int inbound_notify (void *cls, const struct GNUNET_PeerIdentity *other, const struct GNUNET_MessageHeader *message, - struct GNUNET_TIME_Relative latency, - uint32_t distance) + const struct GNUNET_TRANSPORT_ATS_Information *atsi) { total_bytes_recv += ntohs (message->size); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, @@ -207,8 +206,7 @@ static int outbound_notify (void *cls, const struct GNUNET_PeerIdentity *other, const struct GNUNET_MessageHeader *message, - struct GNUNET_TIME_Relative latency, - uint32_t distance) + const struct GNUNET_TRANSPORT_ATS_Information *atsi) { #if DEBUG_CONNECTIONS GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, @@ -238,38 +236,37 @@ static void measurement_end (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { - struct GNUNET_TIME_Relative duration; - - measure_task = GNUNET_SCHEDULER_NO_TASK; - if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)) - return; - - if (err_task != GNUNET_SCHEDULER_NO_TASK) - GNUNET_SCHEDULER_cancel (err_task); - if (send_task != GNUNET_SCHEDULER_NO_TASK) - GNUNET_SCHEDULER_cancel (send_task); - - GNUNET_STATISTICS_get(p1.stats,"core","# discarded CORE_SEND requests",GNUNET_TIME_UNIT_SECONDS, &next_fin, &check_2, &p1); - GNUNET_STATISTICS_get(p1.stats,"core","# discarded CORE_SEND requests",GNUNET_TIME_UNIT_SECONDS, &next_fin, &check_2, &p2); - GNUNET_STATISTICS_get(p1.stats,"core","# discarded lower priority CORE_SEND requests",GNUNET_TIME_UNIT_SECONDS, &next_fin, &check_2, &p1); - GNUNET_STATISTICS_get(p1.stats,"core","# discarded lower priority CORE_SEND requests",GNUNET_TIME_UNIT_SECONDS, &next_fin, &check_2, &p2); - - GNUNET_STATISTICS_get(p1.stats,"core","# discarded CORE_SEND request bytes",GNUNET_TIME_UNIT_SECONDS, &next_fin, &check_2, &p1); - GNUNET_STATISTICS_get(p1.stats,"core","# discarded CORE_SEND request bytes",GNUNET_TIME_UNIT_SECONDS, &next_fin, &check_2, &p2); - GNUNET_STATISTICS_get(p1.stats,"core","# discarded lower priority CORE_SEND request bytes",GNUNET_TIME_UNIT_SECONDS, &next_fin, &check_2, &p1); - GNUNET_STATISTICS_get(p1.stats,"core","# discarded lower priority CORE_SEND request bytes",GNUNET_TIME_UNIT_SECONDS, &next_fin, &check_2, &p2); - measurement_running = GNUNET_NO; - duration = GNUNET_TIME_absolute_get_difference(start_time, GNUNET_TIME_absolute_get()); - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - "\nQuota compliance: \n"\ - "Receive rate: %10llu kB/s\n" - "Send rate : %10llu kB/s\n"\ - "Quota : %10llu kB/s\n", - (total_bytes_recv/(duration.rel_value / 1000)/1024), - (total_bytes_sent/(duration.rel_value / 1000)/1024),current_quota_p1_in/1024); - - - GNUNET_SCHEDULER_add_now (&terminate_task, NULL); + struct GNUNET_TIME_Relative duration; + + measure_task = GNUNET_SCHEDULER_NO_TASK; + if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)) + return; + + if (err_task != GNUNET_SCHEDULER_NO_TASK) + GNUNET_SCHEDULER_cancel (err_task); + if (send_task != GNUNET_SCHEDULER_NO_TASK) + GNUNET_SCHEDULER_cancel (send_task); + + GNUNET_STATISTICS_get(p1.stats,"core","# discarded CORE_SEND requests",GNUNET_TIME_UNIT_SECONDS, &next_fin, &check_2, &p1); + GNUNET_STATISTICS_get(p1.stats,"core","# discarded CORE_SEND requests",GNUNET_TIME_UNIT_SECONDS, &next_fin, &check_2, &p2); + GNUNET_STATISTICS_get(p1.stats,"core","# discarded lower priority CORE_SEND requests",GNUNET_TIME_UNIT_SECONDS, &next_fin, &check_2, &p1); + GNUNET_STATISTICS_get(p1.stats,"core","# discarded lower priority CORE_SEND requests",GNUNET_TIME_UNIT_SECONDS, &next_fin, &check_2, &p2); + + GNUNET_STATISTICS_get(p1.stats,"core","# discarded CORE_SEND request bytes",GNUNET_TIME_UNIT_SECONDS, &next_fin, &check_2, &p1); + GNUNET_STATISTICS_get(p1.stats,"core","# discarded CORE_SEND request bytes",GNUNET_TIME_UNIT_SECONDS, &next_fin, &check_2, &p2); + GNUNET_STATISTICS_get(p1.stats,"core","# discarded lower priority CORE_SEND request bytes",GNUNET_TIME_UNIT_SECONDS, &next_fin, &check_2, &p1); + GNUNET_STATISTICS_get(p1.stats,"core","# discarded lower priority CORE_SEND request bytes",GNUNET_TIME_UNIT_SECONDS, &next_fin, &check_2, &p2); + measurement_running = GNUNET_NO; + duration = GNUNET_TIME_absolute_get_difference(start_time, GNUNET_TIME_absolute_get()); + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "\nQuota compliance: \n" \ + "Receive rate: %10llu kB/s\n" + "Send rate : %10llu kB/s\n" \ + "Quota : %10llu kB/s\n", + (total_bytes_recv/(duration.rel_value / 1000)/1024), + (total_bytes_sent/(duration.rel_value / 1000)/1024), + current_quota_p1_in/1024); + GNUNET_SCHEDULER_add_now (&terminate_task, NULL); } static size_t @@ -279,17 +276,19 @@ static void send_tsk (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { - send_task = GNUNET_SCHEDULER_NO_TASK; - - ch = GNUNET_CORE_notify_transmit_ready (p1.ch, - 0, - FAST_TIMEOUT, - &p2.id, - sizeof (struct TestMessage) + MEASUREMENT_MSG_SIZE, - &transmit_ready, &p1); + send_task = GNUNET_SCHEDULER_NO_TASK; + + ch = GNUNET_CORE_notify_transmit_ready (p1.ch, + 0, + FAST_TIMEOUT, + &p2.id, + sizeof (struct TestMessage) + MEASUREMENT_MSG_SIZE, + &transmit_ready, &p1); } -static void measure (unsigned long long quota_p1, unsigned long long quota_p2 ) + +static void +measure (unsigned long long quota_p1, unsigned long long quota_p2) { #if VERBOSE if ((is_asymmetric_send_constant == GNUNET_YES) || (is_asymmetric_recv_constant == GNUNET_YES)) @@ -316,11 +315,11 @@ static void measure (unsigned long long quota_p1, unsigned long long quota_p2 ) total_bytes = 0; total_bytes_sent = 0; ch = GNUNET_CORE_notify_transmit_ready (p1.ch, - 0, - TIMEOUT, - &p2.id, - sizeof (struct TestMessage) + MEASUREMENT_MSG_SIZE, - &transmit_ready, &p1); + 0, + TIMEOUT, + &p2.id, + sizeof (struct TestMessage) + MEASUREMENT_MSG_SIZE, + &transmit_ready, &p1); } static int tr_n; @@ -330,8 +329,7 @@ static int process_mtype (void *cls, const struct GNUNET_PeerIdentity *peer, const struct GNUNET_MessageHeader *message, - struct GNUNET_TIME_Relative latency, - uint32_t distance) + const struct GNUNET_TRANSPORT_ATS_Information *atsi) { static int n; unsigned int s; @@ -453,7 +451,6 @@ init_notify (void *cls, OKPP; /* connect p2 */ GNUNET_CORE_connect (p2.cfg, 1, - TIMEOUT, &p2, &init_notify, &connect_notify, @@ -534,7 +531,6 @@ run (void *cls, setup_peer (&p1, "test_core_quota_peer1.conf"); setup_peer (&p2, "test_core_quota_peer2.conf"); GNUNET_CORE_connect (p1.cfg, 1, - TIMEOUT, &p1, &init_notify, &connect_notify, @@ -606,7 +602,7 @@ main (int argc, char *argv[]) { int ret; - GNUNET_log_setup ("test-core-api", + GNUNET_log_setup ("test-core-quota-compliance", #if VERBOSE "DEBUG", #else diff --git a/src/dht/gnunet-dht-driver.c b/src/dht/gnunet-dht-driver.c index fdd442cdb..8f1081a7a 100644 --- a/src/dht/gnunet-dht-driver.c +++ b/src/dht/gnunet-dht-driver.c @@ -854,8 +854,6 @@ static void log_topology_cb (void *cls, const struct GNUNET_PeerIdentity *first, const struct GNUNET_PeerIdentity *second, - struct GNUNET_TIME_Relative latency, - uint32_t distance, const char *emsg) { struct TopologyIteratorContext *topo_ctx = cls; @@ -1286,8 +1284,6 @@ static void count_peers_churn_cb (void *cls, const struct GNUNET_PeerIdentity *first, const struct GNUNET_PeerIdentity *second, - struct GNUNET_TIME_Relative latency, - uint32_t distance, const char *emsg) { struct FindPeerContext *find_peer_context = cls; @@ -1958,8 +1954,6 @@ static void count_peers_cb (void *cls, const struct GNUNET_PeerIdentity *first, const struct GNUNET_PeerIdentity *second, - struct GNUNET_TIME_Relative latency, - uint32_t distance, const char *emsg) { struct FindPeerContext *find_peer_context = cls; diff --git a/src/dht/gnunet-service-dht.c b/src/dht/gnunet-service-dht.c index 9e56e99b2..968f9a32f 100644 --- a/src/dht/gnunet-service-dht.c +++ b/src/dht/gnunet-service-dht.c @@ -285,19 +285,21 @@ struct PeerInfo struct GNUNET_CORE_InformationRequestContext *info_ctx; /** - * What is the average latency for replies received? + * What is the identity of the peer? */ - struct GNUNET_TIME_Relative latency; + struct GNUNET_PeerIdentity id; +#if 0 /** - * What is the identity of the peer? + * What is the average latency for replies received? */ - struct GNUNET_PeerIdentity id; + struct GNUNET_TIME_Relative latency; /** * Transport level distance to peer. */ unsigned int distance; +#endif /** * Holds matching bits from peer to current target, @@ -1380,7 +1382,6 @@ update_core_preference (void *cls, * * @param cls closure * @param peer identifies the peer - * @param bpm_in set to the current bandwidth limit (receiving) for this peer * @param bpm_out set to the current bandwidth limit (sending) for this peer * @param amount set to the amount that was actually reserved or unreserved; * either the full requested amount or zero (no partial reservations) @@ -1389,7 +1390,6 @@ update_core_preference (void *cls, static void update_core_preference_finish (void *cls, const struct GNUNET_PeerIdentity * peer, - struct GNUNET_BANDWIDTH_Value32NBO bpm_in, struct GNUNET_BANDWIDTH_Value32NBO bpm_out, int amount, uint64_t preference) { @@ -1416,7 +1416,7 @@ update_core_preference (void *cls, matching = 63; } preference = 1LL << matching; - peer->info_ctx = GNUNET_CORE_peer_change_preference (cfg, + peer->info_ctx = GNUNET_CORE_peer_change_preference (coreAPI, &peer->id, GNUNET_TIME_relative_get_forever(), GNUNET_BANDWIDTH_value_init (UINT32_MAX), @@ -1433,23 +1433,23 @@ update_core_preference (void *cls, * @param peer GNUNET_PeerIdentity of the peer to add * @param bucket the already figured out bucket to add * the peer to - * @param latency the core reported latency of this peer - * @param distance the transport level distance to this peer + * @param atsi performance information * * @return the newly added PeerInfo */ static struct PeerInfo * add_peer(const struct GNUNET_PeerIdentity *peer, unsigned int bucket, - struct GNUNET_TIME_Relative latency, - unsigned int distance) + const struct GNUNET_TRANSPORT_ATS_Information *atsi) { struct PeerInfo *new_peer; GNUNET_assert(bucket < MAX_BUCKETS); GNUNET_assert(peer != NULL); new_peer = GNUNET_malloc(sizeof(struct PeerInfo)); +#if 0 new_peer->latency = latency; new_peer->distance = distance; +#endif memcpy(&new_peer->id, peer, sizeof(struct GNUNET_PeerIdentity)); @@ -1769,8 +1769,7 @@ void schedule_ping_messages() static struct PeerInfo * try_add_peer(const struct GNUNET_PeerIdentity *peer, unsigned int bucket, - struct GNUNET_TIME_Relative latency, - unsigned int distance) + const struct GNUNET_TRANSPORT_ATS_Information *atsi) { int peer_bucket; struct PeerInfo *new_peer; @@ -1781,7 +1780,7 @@ try_add_peer(const struct GNUNET_PeerIdentity *peer, peer_bucket = find_current_bucket(&peer->hashPubKey); GNUNET_assert(peer_bucket >= lowest_bucket); - new_peer = add_peer(peer, peer_bucket, latency, distance); + new_peer = add_peer(peer, peer_bucket, atsi); if ((k_buckets[lowest_bucket].peers_size) >= bucket_size) enable_next_bucket(); @@ -1991,7 +1990,8 @@ static int route_result_message(struct GNUNET_MessageHeader *msg, { increment_stats(STAT_HELLOS_PROVIDED); GNUNET_TRANSPORT_offer_hello(transport_handle, hello_msg); - GNUNET_CORE_peer_request_connect(cfg, GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 5), &new_peer, NULL, NULL); + GNUNET_CORE_peer_request_connect(coreAPI, + GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 5), &new_peer, NULL, NULL); } } } @@ -2420,7 +2420,8 @@ handle_dht_find_peer (const struct GNUNET_MessageHeader *find_msg, { increment_stats(STAT_HELLOS_PROVIDED); GNUNET_TRANSPORT_offer_hello(transport_handle, other_hello); - GNUNET_CORE_peer_request_connect(cfg, GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 5), &peer_id, NULL, NULL); + GNUNET_CORE_peer_request_connect(coreAPI, + GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 5), &peer_id, NULL, NULL); route_message (find_msg, msg_ctx); GNUNET_free (other_hello); return; @@ -4228,7 +4229,7 @@ static int handle_dht_p2p_route_request (void *cls, const struct GNUNET_PeerIdentity *peer, const struct GNUNET_MessageHeader *message, - struct GNUNET_TIME_Relative latency, uint32_t distance) + const struct GNUNET_TRANSPORT_ATS_Information *atsi) { #if DEBUG_DHT GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, @@ -4284,7 +4285,7 @@ static int handle_dht_p2p_route_result (void *cls, const struct GNUNET_PeerIdentity *peer, const struct GNUNET_MessageHeader *message, - struct GNUNET_TIME_Relative latency, uint32_t distance) + const struct GNUNET_TRANSPORT_ATS_Information *atsi) { #if DEBUG_DHT GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, @@ -4472,13 +4473,12 @@ static struct GNUNET_CORE_MessageHandler core_handlers[] = { * * @param cls closure * @param peer peer identity this notification is about - * @param latency reported latency of the connection with peer - * @param distance reported distance (DV) to peer + * @param atsi performance data */ -void handle_core_connect (void *cls, - const struct GNUNET_PeerIdentity * peer, - struct GNUNET_TIME_Relative latency, - uint32_t distance) +static void +handle_core_connect (void *cls, + const struct GNUNET_PeerIdentity * peer, + const struct GNUNET_TRANSPORT_ATS_Information *atsi) { struct PeerInfo *ret; @@ -4497,8 +4497,7 @@ void handle_core_connect (void *cls, GNUNET_DATACACHE_put(datacache, &peer->hashPubKey, sizeof(struct GNUNET_PeerIdentity), (const char *)peer, GNUNET_BLOCK_TYPE_DHT_HELLO, GNUNET_TIME_absolute_get_forever()); ret = try_add_peer(peer, find_current_bucket(&peer->hashPubKey), - latency, - distance); + atsi); if (ret != NULL) { newly_found_peers++; @@ -4517,9 +4516,10 @@ void handle_core_connect (void *cls, * @param cls closure * @param peer peer identity this notification is about */ -void handle_core_disconnect (void *cls, - const struct - GNUNET_PeerIdentity * peer) +static void +handle_core_disconnect (void *cls, + const struct + GNUNET_PeerIdentity * peer) { struct PeerInfo *to_remove; int current_bucket; @@ -4563,7 +4563,6 @@ run (void *cls, GNUNET_SERVER_disconnect_notify (server, &handle_client_disconnect, NULL); coreAPI = GNUNET_CORE_connect (cfg, /* Main configuration */ 1, /* queue size */ - GNUNET_TIME_UNIT_FOREVER_REL, NULL, /* Closure passed to DHT functions */ &core_init, /* Call core_init once connected */ &handle_core_connect, /* Handle connects */ diff --git a/src/dv/Makefile.am b/src/dv/Makefile.am index af3102239..de72438d7 100644 --- a/src/dv/Makefile.am +++ b/src/dv/Makefile.am @@ -28,7 +28,7 @@ libgnunetdv_la_LDFLAGS = \ bin_PROGRAMS = \ gnunet-service-dv - + gnunet_service_dv_SOURCES = \ gnunet-service-dv.c gnunet_service_dv_LDADD = \ diff --git a/src/dv/gnunet-service-dv.c b/src/dv/gnunet-service-dv.c index 6001e33f4..d3897f23d 100644 --- a/src/dv/gnunet-service-dv.c +++ b/src/dv/gnunet-service-dv.c @@ -1311,11 +1311,11 @@ void send_message_delayed (void *cls, * @param latency the latency of the connection we received the message from * @param distance the distance to the immediate peer */ -static int handle_dv_data_message (void *cls, - const struct GNUNET_PeerIdentity * peer, - const struct GNUNET_MessageHeader * message, - struct GNUNET_TIME_Relative latency, - uint32_t distance) +static int +handle_dv_data_message (void *cls, + const struct GNUNET_PeerIdentity * peer, + const struct GNUNET_MessageHeader * message, + const struct GNUNET_TRANSPORT_ATS_Information *atsi) { const p2p_dv_MESSAGE_Data *incoming = (const p2p_dv_MESSAGE_Data *) message; const struct GNUNET_MessageHeader *packed_message; @@ -1919,14 +1919,12 @@ void handle_dv_send_message (void *cls, static int handle_dv_gossip_message (void *cls, const struct GNUNET_PeerIdentity *peer, const struct GNUNET_MessageHeader *message, - struct GNUNET_TIME_Relative latency, - uint32_t distance); + const struct GNUNET_TRANSPORT_ATS_Information *atsi); static int handle_dv_disconnect_message (void *cls, const struct GNUNET_PeerIdentity *peer, const struct GNUNET_MessageHeader *message, - struct GNUNET_TIME_Relative latency, - uint32_t distance); + const struct GNUNET_TRANSPORT_ATS_Information *atsi); /** End forward declarations **/ @@ -2327,7 +2325,8 @@ generate_hello_address (void *cls, size_t max, void *buf) * not added) */ static struct DistantNeighbor * -addUpdateNeighbor (const struct GNUNET_PeerIdentity * peer, struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *pkey, +addUpdateNeighbor (const struct GNUNET_PeerIdentity * peer, + struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *pkey, unsigned int referrer_peer_id, struct DirectNeighbor *referrer, unsigned int cost) { @@ -2466,7 +2465,10 @@ addUpdateNeighbor (const struct GNUNET_PeerIdentity * peer, struct GNUNET_CRYPTO #if DEBUG_DV_MESSAGES GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "%s: learned about peer %llu from which we have a previous unknown message, processing!\n", my_short_id, referrer_peer_id); #endif - handle_dv_data_message(NULL, &referrer->pending_messages[i].sender, referrer->pending_messages[i].message, referrer->pending_messages[i].latency, referrer->pending_messages[i].distance); + handle_dv_data_message(NULL, &referrer->pending_messages[i].sender, + referrer->pending_messages[i].message, + referrer->pending_messages[i].latency, + referrer->pending_messages[i].distance); GNUNET_free(referrer->pending_messages[i].message); referrer->pending_messages[i].sender_id = 0; } @@ -2521,14 +2523,12 @@ addUpdateNeighbor (const struct GNUNET_PeerIdentity * peer, struct GNUNET_CRYPTO * @param cls closure * @param peer peer which sent the message (immediate sender) * @param message the message - * @param latency the latency of the connection we received the message from - * @param distance the distance to the immediate peer + * @param atsi performance data */ static int handle_dv_disconnect_message (void *cls, const struct GNUNET_PeerIdentity *peer, const struct GNUNET_MessageHeader *message, - struct GNUNET_TIME_Relative latency, - uint32_t distance) + const struct GNUNET_TRANSPORT_ATS_Information *atsi) { struct DirectNeighbor *referrer; struct DistantNeighbor *distant; @@ -2570,14 +2570,13 @@ static int handle_dv_disconnect_message (void *cls, * @param cls closure * @param peer peer which sent the message (immediate sender) * @param message the message - * @param latency the latency of the connection we received the message from - * @param distance the distance to the immediate peer + * @param atsi performance data */ -static int handle_dv_gossip_message (void *cls, - const struct GNUNET_PeerIdentity *peer, - const struct GNUNET_MessageHeader *message, - struct GNUNET_TIME_Relative latency, - uint32_t distance) +static int +handle_dv_gossip_message (void *cls, + const struct GNUNET_PeerIdentity *peer, + const struct GNUNET_MessageHeader *message, + const struct GNUNET_TRANSPORT_ATS_Information *atsi) { struct DirectNeighbor *referrer; p2p_dv_MESSAGE_NeighborInfo *enc_message = (p2p_dv_MESSAGE_NeighborInfo *)message; @@ -2623,9 +2622,10 @@ static int handle_dv_gossip_message (void *cls, * * @return GNUNET_YES to continue iteration, GNUNET_NO otherwise */ -static int add_all_extended_peers (void *cls, - const GNUNET_HashCode * key, - void *value) +static int +add_all_extended_peers (void *cls, + const GNUNET_HashCode * key, + void *value) { struct NeighborSendContext *send_context = (struct NeighborSendContext *)cls; struct DistantNeighbor *distant = (struct DistantNeighbor *)value; @@ -2660,9 +2660,10 @@ static int add_all_extended_peers (void *cls, * iterate, * GNUNET_NO if not. */ -static int gossip_all_to_all_iterator (void *cls, - const GNUNET_HashCode * key, - void *abs_value) +static int +gossip_all_to_all_iterator (void *cls, + const GNUNET_HashCode * key, + void *abs_value) { struct DirectNeighbor *direct = abs_value; @@ -2704,9 +2705,10 @@ gossip_all_to_all (void *cls, * * @return GNUNET_YES to continue iteration, GNUNET_NO otherwise */ -static int add_all_direct_neighbors (void *cls, - const GNUNET_HashCode * key, - void *value) +static int +add_all_direct_neighbors (void *cls, + const GNUNET_HashCode * key, + void *value) { struct DirectNeighbor *direct = (struct DirectNeighbor *)value; struct DirectNeighbor *to = (struct DirectNeighbor *)cls; @@ -2832,13 +2834,12 @@ process_peerinfo (void *cls, * * @param cls closure * @param peer peer identity this notification is about - * @param latency reported latency of the connection with peer - * @param distance reported distance (DV) to peer + * @param atsi performance data */ -void handle_core_connect (void *cls, - const struct GNUNET_PeerIdentity * peer, - struct GNUNET_TIME_Relative latency, - uint32_t distance) +static void +handle_core_connect (void *cls, + const struct GNUNET_PeerIdentity * peer, + const struct GNUNET_TRANSPORT_ATS_Information *atsi) { struct DirectNeighbor *neighbor; struct DistantNeighbor *about; @@ -2994,7 +2995,6 @@ run (void *cls, coreAPI = GNUNET_CORE_connect (cfg, 1, - GNUNET_TIME_relative_get_forever(), NULL, /* FIXME: anything we want to pass around? */ &core_init, &handle_core_connect, diff --git a/src/fs/gnunet-service-fs.c b/src/fs/gnunet-service-fs.c index fd4ec74ed..139cb5aa9 100644 --- a/src/fs/gnunet-service-fs.c +++ b/src/fs/gnunet-service-fs.c @@ -1555,26 +1555,40 @@ destroy_pending_request (struct PendingRequest *pr) } +/** + * Find latency information in 'atsi'. + * + * @param atsi performance data + * @return connection latency + */ +static struct GNUNET_TIME_Relative +get_latency (const struct GNUNET_TRANSPORT_ATS_Information *atsi) +{ + /* FIXME: extract latency data from 'atsi' */ + return GNUNET_TIME_UNIT_SECONDS; +} + + /** * Method called whenever a given peer connects. * * @param cls closure, not used * @param peer peer identity this notification is about - * @param latency reported latency of the connection with 'other' - * @param distance reported distance (DV) to 'other' + * @param atsi performance information */ static void peer_connect_handler (void *cls, const struct GNUNET_PeerIdentity * peer, - struct GNUNET_TIME_Relative latency, - uint32_t distance) + const struct GNUNET_TRANSPORT_ATS_Information *atsi) { struct ConnectedPeer *cp; struct MigrationReadyBlock *pos; char *fn; uint32_t trust; + struct GNUNET_TIME_Relative latency; + latency = get_latency (atsi); cp = GNUNET_CONTAINER_multihashmap_get (connected_peers, &peer->hashPubKey); if (NULL != cp) @@ -1612,25 +1626,25 @@ peer_connect_handler (void *cls, * * @param cls closure * @param peer peer identity this notification is about - * @param latency reported latency of the connection with 'other' - * @param distance reported distance (DV) to 'other' * @param bandwidth_in available amount of inbound bandwidth * @param bandwidth_out available amount of outbound bandwidth * @param timeout absolute time when this peer will time out * unless we see some further activity from it + * @param atsi status information */ static void peer_status_handler (void *cls, const struct GNUNET_PeerIdentity * peer, - struct GNUNET_TIME_Relative latency, - uint32_t distance, struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in, struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out, - struct GNUNET_TIME_Absolute timeout) + struct GNUNET_TIME_Absolute timeout, + const struct GNUNET_TRANSPORT_ATS_Information *atsi) { struct ConnectedPeer *cp; + struct GNUNET_TIME_Relative latency; + latency = get_latency (atsi); cp = GNUNET_CONTAINER_multihashmap_get (connected_peers, &peer->hashPubKey); if (cp == NULL) @@ -2529,7 +2543,6 @@ refresh_bloomfilter (struct PendingRequest *pr) * * @param cls the requests "struct PendingRequest*" * @param peer identifies the peer - * @param bpm_in set to the current bandwidth limit (receiving) for this peer * @param bpm_out set to the current bandwidth limit (sending) for this peer * @param amount set to the amount that was actually reserved or unreserved * @param preference current traffic preference for the given peer @@ -2538,7 +2551,6 @@ static void target_reservation_cb (void *cls, const struct GNUNET_PeerIdentity * peer, - struct GNUNET_BANDWIDTH_Value32NBO bpm_in, struct GNUNET_BANDWIDTH_Value32NBO bpm_out, int amount, uint64_t preference) @@ -2984,7 +2996,7 @@ forward_request_task (void *cls, cp = GNUNET_CONTAINER_multihashmap_get (connected_peers, &psc.target.hashPubKey); GNUNET_assert (NULL != cp); - pr->irc = GNUNET_CORE_peer_change_preference (cfg, + pr->irc = GNUNET_CORE_peer_change_preference (core, &psc.target, GNUNET_CONSTANTS_SERVICE_TIMEOUT, GNUNET_BANDWIDTH_value_init (UINT32_MAX), @@ -2999,7 +3011,7 @@ forward_request_task (void *cls, /* force forwarding */ static struct GNUNET_BANDWIDTH_Value32NBO zerobw; target_reservation_cb (pr, &psc.target, - zerobw, zerobw, 0, 0.0); + zerobw, 0, 0.0); } } @@ -3467,8 +3479,7 @@ put_migration_continuation (void *cls, * @param other the other peer involved (sender or receiver, NULL * for loopback messages where we are both sender and receiver) * @param message the actual message - * @param latency reported latency of the connection with 'other' - * @param distance reported distance (DV) to 'other' + * @param atsi performance information * @return GNUNET_OK to keep the connection open, * GNUNET_SYSERR to close it (signal serious error) */ @@ -3476,8 +3487,7 @@ static int handle_p2p_put (void *cls, const struct GNUNET_PeerIdentity *other, const struct GNUNET_MessageHeader *message, - struct GNUNET_TIME_Relative latency, - uint32_t distance) + const struct GNUNET_TRANSPORT_ATS_Information *atsi) { const struct PutMessage *put; uint16_t msize; @@ -3608,8 +3618,7 @@ handle_p2p_put (void *cls, * @param other the other peer involved (sender or receiver, NULL * for loopback messages where we are both sender and receiver) * @param message the actual message - * @param latency reported latency of the connection with 'other' - * @param distance reported distance (DV) to 'other' + * @param atsi performance information * @return GNUNET_OK to keep the connection open, * GNUNET_SYSERR to close it (signal serious error) */ @@ -3617,8 +3626,7 @@ static int handle_p2p_migration_stop (void *cls, const struct GNUNET_PeerIdentity *other, const struct GNUNET_MessageHeader *message, - struct GNUNET_TIME_Relative latency, - uint32_t distance) + const struct GNUNET_TRANSPORT_ATS_Information *atsi) { struct ConnectedPeer *cp; const struct MigrationStopMessage *msm; @@ -3955,8 +3963,7 @@ check_duplicate_request_peer (void *cls, * @param other the other peer involved (sender or receiver, NULL * for loopback messages where we are both sender and receiver) * @param message the actual message - * @param latency reported latency of the connection with 'other' - * @param distance reported distance (DV) to 'other' + * @param atsi performance information * @return GNUNET_OK to keep the connection open, * GNUNET_SYSERR to close it (signal serious error) */ @@ -3964,8 +3971,7 @@ static int handle_p2p_get (void *cls, const struct GNUNET_PeerIdentity *other, const struct GNUNET_MessageHeader *message, - struct GNUNET_TIME_Relative latency, - uint32_t distance) + const struct GNUNET_TRANSPORT_ATS_Information *atsi) { struct PendingRequest *pr; struct ConnectedPeer *cp; @@ -4491,7 +4497,6 @@ main_init (struct GNUNET_SERVER_Handle *server, requests_by_expiration_heap = GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MIN); core = GNUNET_CORE_connect (cfg, 1, /* larger? */ - GNUNET_TIME_UNIT_FOREVER_REL, NULL, NULL, &peer_connect_handler, diff --git a/src/hostlist/gnunet-daemon-hostlist.c b/src/hostlist/gnunet-daemon-hostlist.c index 8c3bb9be7..bd76b17d3 100644 --- a/src/hostlist/gnunet-daemon-hostlist.c +++ b/src/hostlist/gnunet-daemon-hostlist.c @@ -141,13 +141,12 @@ core_init (void *cls, * Core handler for p2p hostlist advertisements */ static int advertisement_handler (void *cls, - const struct GNUNET_PeerIdentity * peer, - const struct GNUNET_MessageHeader * message, - struct GNUNET_TIME_Relative latency, - uint32_t distance) + const struct GNUNET_PeerIdentity * peer, + const struct GNUNET_MessageHeader * message, + const struct GNUNET_TRANSPORT_ATS_Information *atsi) { GNUNET_assert (NULL != client_adv_handler); - return (*client_adv_handler) (cls, peer, message, latency, distance); + return (*client_adv_handler) (cls, peer, message, atsi); } @@ -156,23 +155,21 @@ static int advertisement_handler (void *cls, * * @param cls closure * @param peer peer identity this notification is about - * @param latency reported latency of the connection with 'other' - * @param distance reported distance (DV) to 'other' + * @param atsi performance data */ static void connect_handler (void *cls, const struct GNUNET_PeerIdentity * peer, - struct GNUNET_TIME_Relative latency, - uint32_t distance) + const struct GNUNET_TRANSPORT_ATS_Information *atsi) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "A new peer connected, notifying client and server\n"); if ( NULL != client_ch) - (*client_ch) (cls, peer, latency, distance); + (*client_ch) (cls, peer, atsi); #if HAVE_MHD if ( NULL != server_ch) - (*server_ch) (cls, peer, latency, distance); + (*server_ch) (cls, peer, atsi); #endif } @@ -270,7 +267,6 @@ run (void *cls, core = GNUNET_CORE_connect (cfg, 1, - GNUNET_TIME_UNIT_FOREVER_REL, NULL, &core_init, &connect_handler, &disconnect_handler, NULL, diff --git a/src/hostlist/hostlist-client.c b/src/hostlist/hostlist-client.c index 9e5cbda65..503adb8a0 100644 --- a/src/hostlist/hostlist-client.c +++ b/src/hostlist/hostlist-client.c @@ -1137,15 +1137,13 @@ task_hostlist_saving (void *cls, * * @param cls closure * @param peer peer identity this notification is about - * @param latency reported latency of the connection with 'other' - * @param distance reported distance (DV) to 'other' + * @param atsi performance data */ static void handler_connect (void *cls, const struct GNUNET_PeerIdentity * peer, - struct GNUNET_TIME_Relative latency, - uint32_t distance) + const struct GNUNET_TRANSPORT_ATS_Information *atsi) { GNUNET_assert (stat_connection_count < UINT_MAX); stat_connection_count++; @@ -1181,17 +1179,15 @@ handler_disconnect (void *cls, * @param cls closure (always NULL) * @param peer the peer sending the message * @param message the actual message - * @param latency latency - * @param distance distance + * @param atsi performance data * @return GNUNET_OK to keep the connection open, * GNUNET_SYSERR to close it (signal serious error) */ static int handler_advertisement (void *cls, - const struct GNUNET_PeerIdentity * peer, - const struct GNUNET_MessageHeader * message, - struct GNUNET_TIME_Relative latency, - uint32_t distance) + const struct GNUNET_PeerIdentity * peer, + const struct GNUNET_MessageHeader * message, + const struct GNUNET_TRANSPORT_ATS_Information *atsi) { size_t size; size_t uri_size; diff --git a/src/hostlist/hostlist-server.c b/src/hostlist/hostlist-server.c index 1c85f8f75..95272a555 100644 --- a/src/hostlist/hostlist-server.c +++ b/src/hostlist/hostlist-server.c @@ -376,15 +376,13 @@ adv_transmit_ready ( void *cls, size_t size, void *buf) * * @param cls closure * @param peer peer identity this notification is about - * @param latency reported latency of the connection with 'other' - * @param distance reported distance (DV) to 'other' + * @param atsi performance data */ static void connect_handler (void *cls, const struct GNUNET_PeerIdentity * peer, - struct GNUNET_TIME_Relative latency, - uint32_t distance) + const struct GNUNET_TRANSPORT_ATS_Information *atsi) { size_t size; diff --git a/src/hostlist/test_gnunet_daemon_hostlist_learning.c b/src/hostlist/test_gnunet_daemon_hostlist_learning.c index d64fdf587..c780c128b 100644 --- a/src/hostlist/test_gnunet_daemon_hostlist_learning.c +++ b/src/hostlist/test_gnunet_daemon_hostlist_learning.c @@ -283,11 +283,11 @@ check_statistics (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) /** * Core handler for p2p hostlist advertisements */ -static int ad_arrive_handler (void *cls, - const struct GNUNET_PeerIdentity * peer, - const struct GNUNET_MessageHeader * message, - struct GNUNET_TIME_Relative latency, - uint32_t distance) +static int +ad_arrive_handler (void *cls, + const struct GNUNET_PeerIdentity * peer, + const struct GNUNET_MessageHeader * message, + const struct GNUNET_TRANSPORT_ATS_Information *atsi) { char *hostname; char *expected_uri; @@ -371,7 +371,6 @@ setup_learn_peer (struct PeerContext *p, const char *cfgname) p->core = GNUNET_CORE_connect (p->cfg, 1, - GNUNET_TIME_UNIT_FOREVER_REL, NULL, NULL, NULL, NULL, NULL, diff --git a/src/include/gnunet_core_service.h b/src/include/gnunet_core_service.h index 9c102988b..abfcd1d3b 100644 --- a/src/include/gnunet_core_service.h +++ b/src/include/gnunet_core_service.h @@ -37,6 +37,7 @@ extern "C" #endif #include "gnunet_util_lib.h" +#include "gnunet_transport_service.h" /** * Version number of GNUnet-core API. @@ -55,35 +56,32 @@ struct GNUNET_CORE_Handle; * * @param cls closure * @param peer peer identity this notification is about - * @param latency reported latency of the connection with 'other' - * @param distance reported distance (DV) to 'other' + * @param atsi performance data for the connection */ typedef void (*GNUNET_CORE_ConnectEventHandler) (void *cls, const struct - GNUNET_PeerIdentity * peer, - struct GNUNET_TIME_Relative latency, - uint32_t distance); + GNUNET_PeerIdentity *peer, + const struct GNUNET_TRANSPORT_ATS_Information *atsi); + /** * Method called whenever a given peer has a status change. * * @param cls closure * @param peer peer identity this notification is about - * @param latency reported latency of the connection with 'other' - * @param distance reported distance (DV) to 'other' - * @param bandwidth_in available amount of inbound bandwidth - * @param bandwidth_out available amount of outbound bandwidth * @param timeout absolute time when this peer will time out * unless we see some further activity from it + * @param bandwidth_in available amount of inbound bandwidth + * @param bandwidth_out available amount of outbound bandwidth + * @param atsi performance data for the connection */ typedef void (*GNUNET_CORE_PeerStatusEventHandler) (void *cls, const struct GNUNET_PeerIdentity * peer, - struct GNUNET_TIME_Relative latency, - uint32_t distance, struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in, struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out, - struct GNUNET_TIME_Absolute timeout); + struct GNUNET_TIME_Absolute timeout, + const struct GNUNET_TRANSPORT_ATS_Information *atsi); /** @@ -94,29 +92,26 @@ typedef void (*GNUNET_CORE_PeerStatusEventHandler) (void *cls, */ typedef void (*GNUNET_CORE_DisconnectEventHandler) (void *cls, const struct - GNUNET_PeerIdentity * peer); + GNUNET_PeerIdentity *peer); /** * Functions with this signature are called whenever a message is * received or transmitted. * - * @param cls closure + * @param cls closure (set from GNUNET_CORE_connect) * @param peer the other peer involved (sender or receiver, NULL * for loopback messages where we are both sender and receiver) * @param message the actual message - * @param latency reported latency of the connection with 'other' - * @param distance reported distance (DV) to 'other' + * @param atsi performance data for the connection * @return GNUNET_OK to keep the connection open, * GNUNET_SYSERR to close it (signal serious error) */ typedef int (*GNUNET_CORE_MessageCallback) (void *cls, - const struct GNUNET_PeerIdentity * other, - const struct GNUNET_MessageHeader * - message, - struct GNUNET_TIME_Relative latency, - uint32_t distance); + const struct GNUNET_PeerIdentity *other, + const struct GNUNET_MessageHeader *message, + const struct GNUNET_TRANSPORT_ATS_Information *atsi); /** @@ -180,7 +175,6 @@ typedef void * * @param cfg configuration to use * @param queue_size size of the per-peer message queue - * @param timeout after how long should we give up trying to connect to the core service? * @param cls closure for the various callbacks that follow (including handlers in the handlers array) * @param init callback to call on timeout or once we have successfully * connected to the core service; note that timeout is only meaningful if init is not NULL @@ -217,7 +211,6 @@ typedef void struct GNUNET_CORE_Handle * GNUNET_CORE_connect (const struct GNUNET_CONFIGURATION_Handle *cfg, unsigned int queue_size, - struct GNUNET_TIME_Relative timeout, void *cls, GNUNET_CORE_StartupCallback init, GNUNET_CORE_ConnectEventHandler connects, @@ -231,7 +224,9 @@ GNUNET_CORE_connect (const struct GNUNET_CONFIGURATION_Handle *cfg, /** - * Disconnect from the core service. + * Disconnect from the core service. This function can only + * be called *after* all pending 'GNUNET_CORE_notify_transmit_ready' + * requests have been explicitly cancelled. * * @param handle connection to core to disconnect */ @@ -257,7 +252,7 @@ struct GNUNET_CORE_PeerRequestHandle; * to our connection attempt within the given time frame, 'cont' will * be called with the TIMEOUT reason code. * - * @param cfg configuration to use + * @param h core handle * @param timeout how long to try to talk to core * @param peer who should we connect to * @param cont function to call once the request has been completed (or timed out) @@ -265,7 +260,7 @@ struct GNUNET_CORE_PeerRequestHandle; * @return NULL on error (cont will not be called), otherwise handle for cancellation */ struct GNUNET_CORE_PeerRequestHandle * -GNUNET_CORE_peer_request_connect (const struct GNUNET_CONFIGURATION_Handle *cfg, +GNUNET_CORE_peer_request_connect (struct GNUNET_CORE_Handle *h, struct GNUNET_TIME_Relative timeout, const struct GNUNET_PeerIdentity * peer, GNUNET_SCHEDULER_Task cont, @@ -283,14 +278,11 @@ GNUNET_CORE_peer_request_connect_cancel (struct GNUNET_CORE_PeerRequestHandle *r /** - * Function called with statistics about the given peer. + * Function called with perference change information about the given peer. * * @param cls closure * @param peer identifies the peer - * @param bpm_in set to the current bandwidth limit (receiving) for this peer - * @param bpm_out set to the current bandwidth limit (sending) for this peer - * @param latency current latency estimate, "FOREVER" if we have been - * disconnected + * @param bandwidth_out available amount of outbound bandwidth * @param amount set to the amount that was actually reserved or unreserved; * either the full requested amount or zero (no partial reservations) * @param preference current traffic preference for the given peer @@ -299,8 +291,7 @@ typedef void (*GNUNET_CORE_PeerConfigurationInfoCallback) (void *cls, const struct GNUNET_PeerIdentity * peer, - struct GNUNET_BANDWIDTH_Value32NBO bpm_in, - struct GNUNET_BANDWIDTH_Value32NBO bpm_out, + struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out, int amount, uint64_t preference); @@ -314,8 +305,9 @@ struct GNUNET_CORE_InformationRequestContext; /** * Obtain statistics and/or change preferences for the given peer. + * You can only have one such pending request per peer. * - * @param cfg configuration to use + * @param h core handle * @param peer identifies the peer * @param timeout after how long should we give up (and call "info" with NULL * for "peer" to signal an error)? @@ -337,7 +329,7 @@ struct GNUNET_CORE_InformationRequestContext; * @return NULL on error */ struct GNUNET_CORE_InformationRequestContext * -GNUNET_CORE_peer_change_preference (const struct GNUNET_CONFIGURATION_Handle *cfg, +GNUNET_CORE_peer_change_preference (struct GNUNET_CORE_Handle *h, const struct GNUNET_PeerIdentity *peer, struct GNUNET_TIME_Relative timeout, struct GNUNET_BANDWIDTH_Value32NBO bw_out, @@ -349,25 +341,33 @@ GNUNET_CORE_peer_change_preference (const struct GNUNET_CONFIGURATION_Handle *cf /** * Cancel request for getting information about a peer. + * Note that an eventual change in preference, trust or bandwidth + * assignment MAY have already been committed at the time, + * so cancelling a request is NOT sure to undo the original + * request. The original request may or may not still commit. + * The only thing cancellation ensures is that the callback + * from the original request will no longer be called. * * @param irc context returned by the original GNUNET_CORE_peer_get_info call */ void GNUNET_CORE_peer_change_preference_cancel (struct GNUNET_CORE_InformationRequestContext *irc); + /** - * Obtain statistics and/or change preferences for the given peer. + * Iterate over all connected peers. * - * @param cfg configuration to use + * @param h core handle * @param peer_cb function to call with the peer information * @param cb_cls closure for peer_cb - * @return GNUNET_OK if iterating, GNUNET_SYSERR on error + * @return GNUNET_OK on success, GNUNET_SYSERR on errors */ int -GNUNET_CORE_iterate_peers (const struct GNUNET_CONFIGURATION_Handle *cfg, +GNUNET_CORE_iterate_peers (struct GNUNET_CORE_Handle *h, GNUNET_CORE_ConnectEventHandler peer_cb, void *cb_cls); + /** * Handle for a transmission request. */ diff --git a/src/include/gnunet_protocols.h b/src/include/gnunet_protocols.h index 0bcd59838..4d9fec4ca 100644 --- a/src/include/gnunet_protocols.h +++ b/src/include/gnunet_protocols.h @@ -357,19 +357,26 @@ extern "C" #define GNUNET_MESSAGE_TYPE_CORE_CONFIGURATION_INFO 73 /** - * Request from client with message to transmit. + * Request from client to transmit message. */ -#define GNUNET_MESSAGE_TYPE_CORE_SEND 74 +#define GNUNET_MESSAGE_TYPE_CORE_SEND_REQUEST 74 /** - * Request from client asking to connect to a peer. + * Confirmation from core that message can now be sent + */ +#define GNUNET_MESSAGE_TYPE_CORE_SEND_READY 75 + +/** + * Client with message to transmit (after SEND_READY confirmation + * was received). */ -#define GNUNET_MESSAGE_TYPE_CORE_REQUEST_CONNECT 75 +#define GNUNET_MESSAGE_TYPE_CORE_SEND 76 /** - * Request from client asking to call back with all connected peers. + * Request from client asking to connect to a peer. */ -#define GNUNET_MESSAGE_TYPE_CORE_ITERATE_PEERS 76 +#define GNUNET_MESSAGE_TYPE_CORE_REQUEST_CONNECT 77 + /** * Session key exchange between peers. diff --git a/src/include/gnunet_testing_lib.h b/src/include/gnunet_testing_lib.h index 97bc36a79..2e8a04594 100644 --- a/src/include/gnunet_testing_lib.h +++ b/src/include/gnunet_testing_lib.h @@ -395,8 +395,6 @@ typedef void (*GNUNET_TESTING_NotifyConnection)(void *cls, typedef void (*GNUNET_TESTING_NotifyTopology)(void *cls, const struct GNUNET_PeerIdentity *first, const struct GNUNET_PeerIdentity *second, - struct GNUNET_TIME_Relative latency, - uint32_t distance, const char *emsg); /** diff --git a/src/include/gnunet_transport_plugin.h b/src/include/gnunet_transport_plugin.h index d367779e1..31138e8f5 100644 --- a/src/include/gnunet_transport_plugin.h +++ b/src/include/gnunet_transport_plugin.h @@ -36,341 +36,6 @@ #include "gnunet_statistics_service.h" #include "gnunet_transport_service.h" - -/** - * The structs defined here are used by the transport plugin to tell ATS about - * the transport's properties like cost and quality and on the other side - * the structs are used by highlevel components to communicate the constraints - * they have for a transport to ATS - * - * +---+ - * +-----------+ Constraints | | Plugin properties +---------+ - * | Highlevel |------------> |ATS| <------------------|Transport| - * | Component | ATS struct | | ATS struct | Plugin | - * +-----------+ | | +---------+ - * +---+ - * - */ - -#define GNUNET_TRANSPORT_ATS_ARRAY_TERMINATOR 0 - -/** - * Enum defining all known property types for ATS - * Enum values are used in the GNUNET_TRANSPORT_ATS_Information struct as (key,value)-pair - * - * Cost are always stored in uint32_t, so all units used to define costs - * have to be normalized to fit in uint32_t [0 .. 4.294.967.295] - * - * To keep the elements ordered - * 1..1024 : Values with a relation to cost - * 1025..2048 : Values with a relation to quality - * 2049..3072 : Values with a relation to availability - * - */ -enum GNUNET_TRANSPORT_ATS_Property -{ - - /* Cost related values */ - /* =================== */ - - /** - * Volume based cost in financial units to transmit data - * - * Note: This value is not bound to a specific currency or unit and only - * used locally. - * "cent" just refers the smallest amount of money in the respective - * currency. - * - * Unit: [cent/MB] - * - * Interpretation: less is better - * - * Examples: - * LAN: 0 [cent/MB] - * 2G : 10 [cent/MB] - */ - GNUNET_TRANSPORT_ATS_COST_FINANCIAL_PER_VOLUME = 1, - - /** - * Time based cost in financial units to transmit data - * - * Note: This value is not bound to a specific currency or unit and only - * used locally. - * "cent" just refers the smallest amount of money in the respective - * currency. - * - * Unit: [cent/h] - * - * Interpretation: less is better - * - * Examples: - * LAN : 0 [cent/h] - * Dialup: 10 [cent/h] - */ - GNUNET_TRANSPORT_ATS_COST_FINANCIAL_PER_TIME = 2, - - /** - * Computational costs - * - * Effort of preparing data to be sent with this transport - * Includes encoding, encryption and conversion of data - * Partial values can be summed up: c_sum = c_enc + c_enc + c_conv - * Resulting values depend on local system properties, e.g. CPU - * - * Unit: [ms/GB] - * - * Interpretation: less is better - * - * Examples: - * - * HTTPS with AES CBC-256: 7,382 - * HTTPS with AES CBC-128: 5,279 - * HTTPS with RC4-1024: 2,652 - */ - GNUNET_TRANSPORT_ATS_COST_COMPUTATIONAL = 3, - - /** - * Energy consumption - * - * Energy consumption using this transport when sending with a certain - * power at a certain bitrate. This is only an approximation based on: - * Energy consumption E = P / D - * - * with: - * Power P in Watt (J/s) - * Datarate D in MBit/s - * - * Conversion between power P and dBm used by WLAN in radiotap's dBm TX power: - * - * Lp(dbm) = 10 log10 (P/ 1mW) - * - * => P = 1 mW * 10^(Lp(dbm)/10) - * - * Unit: [mJ/MB] - * - * Interpretation: less is better - * - * Examples: - * - * LAN: 0 - * WLAN: 89 (600 mW @ 802.11g /w 54 MBit/s) - * Bluetooth: 267 (100 mW @ BT2.0 EDR /w 3 MBit/s) - */ - GNUNET_TRANSPORT_ATS_COST_ENERGY_CONSUMPTION = 4, - - /** - * Connect cost - * How many bytes are transmitted to initiate a new connection using - * this transport? - * - * Unit: [bytes] - * - * Interpretation: less is better - * - * Examples: - * - * UDP (No connection) : - * 0 bytes - * TCP (TCP 3-Way handshake): - * 220 bytes Ethernet, 172 bytes TCP/IP, 122 bytes TCP - * HTTP (TCP + Header) : - * 477 bytes Ethernet, 429 bytes TCP/IP, 374 bytes TCP, 278 bytes HTTP - * HTTPS HTTP+TLS Handshake: - * 2129 bytes Ethernet, 1975 bytes TCP/IP, 1755 bytes TCP, 1403 bytes HTTPS - * - * */ - GNUNET_TRANSPORT_ATS_COST_CONNECT = 5, - - /** - * Bandwidth cost - * - * How many bandwidth is available to consume? - * Used to calculate which impact sending data with this transport has - * - * Unit: [kB/s] - * - * Interpretation: more is better - * - * Examples: - * LAN: 12,800 (100 MBit/s) - * WLAN: 6,912 (54 MBit/s) - * Dial-up: 8 (64 Kbit/s) - * - */ - GNUNET_TRANSPORT_ATS_COST_BANDWITH_AVAILABLE = 6, - - /** - * Network overhead - * - * How many bytes are sent over the wire when 1 kilobyte (1024 bytes) - * of application data is transmitted? - * A factor used with connect cost, bandwidth cost and energy cost - * to describe the overhead produced by the transport protocol - * - * Unit: [bytes/kb] - * - * Interpretation: less is better - * - * Examples: - * - * TCP/IPv4 over Ethernet: 1024 + 38 + 20 + 20 = 1102 [bytes/kb] - * TCP/IPv6 over Ethernet: 1024 + 38 + 20 + 40 = 1122 [bytes/kb] - * UDP/IPv4 over Ethernet: 1024 + 38 + 20 + 8 = 1090 [bytes/kb] - * UDP/IPv6 over Ethernet: 1024 + 38 + 40 + 8 = 1110 [bytes/kb] - */ - GNUNET_TRANSPORT_ATS_COST_NETWORK_OVERHEAD = 7, - - - /* Quality related values */ - /* ====================== */ - - /* Physical layer quality properties */ - - /** - * Signal strength on physical layer - * - * Unit: [dBm] - */ - GNUNET_TRANSPORT_ATS_QUALITY_PHY_SIGNAL_STRENGTH = 1025, - - /** - * Collision rate on physical layer - * - * Unit: [B/s] - */ - GNUNET_TRANSPORT_ATS_QUALITY_PHY_COLLISION_RATE = 1026, - - /** - * Error rate on physical layer - * - * Unit: [B/s] - */ - GNUNET_TRANSPORT_ATS_QUALITY_PHY_ERROR_RATE = 1027, - - /* Network layer quality properties */ - - /** - * Delay - * Time between when the time packet is sent and the packet arrives - * - * Unit: [μs] - * - * Examples: - * - * LAN : 180 - * Dialup: 4000 - * WLAN : 7000 - */ - GNUNET_TRANSPORT_ATS_QUALITY_NET_DELAY = 1028, - - /** - * Jitter - * Time variations of the delay - * 1st derivative of a delay function - * - * Unit: [μs] - */ - GNUNET_TRANSPORT_ATS_QUALITY_NET_JITTER = 1029, - - /** - * Error rate on network layer - * - * Unit: [B/s] - * - * Examples: - * - * LAN : 0 - * WLAN : 400 - * Bluetooth : 100 - * Note: This numbers are just assumptions as an example, not - * measured or somehow determined - */ - GNUNET_TRANSPORT_ATS_QUALITY_NET_ERRORRATE = 1030, - - /** - * Drop rate on network layer - * Bytes actively dismissed by a network component during transmission - * Reasons for dropped data can be full queues, congestion, quota violations... - * - * Unit: [B/s] - * - * Examples: - * - * LAN : 0 - * WLAN : 400 - * Bluetooth : 100 - * Note: This numbers are just assumptions as an example, not - * measured or somehow determined - */ - GNUNET_TRANSPORT_ATS_QUALITY_NET_DROPRATE = 1031, - - /** - * Loss rate on network layer - * Bytes lost during transmission - * Reasons can be collisions, ... - * - * Unit: [B/s] - * - * Examples: - * - * LAN : 0 - * WLAN : 40 - * Bluetooth : 10 - * Note: This numbers are just assumptions as an example, not measured - * or somehow determined - */ - GNUNET_TRANSPORT_ATS_QUALITY_NET_LOSSRATE = 1032, - - /** - * Throughput on network layer - * - * Unit: [kB/s] - * - * Examples: - * - * LAN : 3400 - * WLAN : 1200 - * Dialup: 4 - * - */ - GNUNET_TRANSPORT_ATS_QUALITY_NET_THROUGHPUT = 1033, - - /* Availability related values */ - /* =========================== */ - - /** - * Is a peer reachable? - */ - GNUNET_TRANSPORT_ATS_AVAILABILITY_REACHABLE = 2048, - - /** - * Is there a connection established to a peer using this transport - */ - GNUNET_TRANSPORT_ATS_AVAILABILITY_CONNECTED = 2049 -}; - -/** - * This structure will be used by plugins to communicate costs to ATS or by - * higher level components to tell ATS their constraints. - * Always a pair of (GNUNET_TRANSPORT_ATS_Property, uint32_t value). - * Value is always uint32_t, so all units used to define costs have to - * be normalized to fit uint32_t. - */ -struct GNUNET_TRANSPORT_ATS_Information -{ - /** - * ATS property type - */ - uint32_t type; - - /** - * ATS property value - */ - uint32_t value; -}; - - - /** * Opaque pointer that plugins can use to distinguish specific * connections to a given peer. Typically used by stateful plugins to diff --git a/src/include/gnunet_transport_service.h b/src/include/gnunet_transport_service.h index eddd8f8af..fcd91e6ec 100644 --- a/src/include/gnunet_transport_service.h +++ b/src/include/gnunet_transport_service.h @@ -47,6 +47,344 @@ extern "C" */ #define GNUNET_TRANSPORT_VERSION 0x00000000 + +/** + * Enum defining all known property types for ATS Enum values are used + * in the GNUNET_TRANSPORT_ATS_Information struct as + * (key,value)-pairs. + * + * Cost are always stored in uint32_t, so all units used to define costs + * have to be normalized to fit in uint32_t [0 .. 4.294.967.295] + * + * To keep the elements ordered + * 1..1024 : Values with a relation to cost + * 1025..2048 : Values with a relation to quality + * 2049..3072 : Values with a relation to availability + * + */ +enum GNUNET_TRANSPORT_ATS_Property +{ + + /** + * End of the array. + */ + GNUNET_TRANSPORT_ATS_ARRAY_TERMINATOR = 0, + + /* Cost related values */ + /* =================== */ + + /** + * Volume based cost in financial units to transmit data + * + * Note: This value is not bound to a specific currency or unit and only + * used locally. + * "cent" just refers the smallest amount of money in the respective + * currency. + * + * Unit: [cent/MB] + * + * Interpretation: less is better + * + * Examples: + * LAN: 0 [cent/MB] + * 2G : 10 [cent/MB] + */ + GNUNET_TRANSPORT_ATS_COST_FINANCIAL_PER_VOLUME = 1, + + /** + * Time based cost in financial units to transmit data + * + * Note: This value is not bound to a specific currency or unit and only + * used locally. + * "cent" just refers the smallest amount of money in the respective + * currency. + * + * Unit: [cent/h] + * + * Interpretation: less is better + * + * Examples: + * LAN : 0 [cent/h] + * Dialup: 10 [cent/h] + */ + GNUNET_TRANSPORT_ATS_COST_FINANCIAL_PER_TIME = 2, + + /** + * Computational costs + * + * Effort of preparing data to be sent with this transport + * Includes encoding, encryption and conversion of data + * Partial values can be summed up: c_sum = c_enc + c_enc + c_conv + * Resulting values depend on local system properties, e.g. CPU + * + * Unit: [ms/GB] + * + * Interpretation: less is better + * + * Examples: + * + * HTTPS with AES CBC-256: 7,382 + * HTTPS with AES CBC-128: 5,279 + * HTTPS with RC4-1024: 2,652 + */ + GNUNET_TRANSPORT_ATS_COST_COMPUTATIONAL = 3, + + /** + * Energy consumption + * + * Energy consumption using this transport when sending with a certain + * power at a certain bitrate. This is only an approximation based on: + * Energy consumption E = P / D + * + * with: + * Power P in Watt (J/s) + * Datarate D in MBit/s + * + * Conversion between power P and dBm used by WLAN in radiotap's dBm TX power: + * + * Lp(dbm) = 10 log10 (P/ 1mW) + * + * => P = 1 mW * 10^(Lp(dbm)/10) + * + * Unit: [mJ/MB] + * + * Interpretation: less is better + * + * Examples: + * + * LAN: 0 + * WLAN: 89 (600 mW @ 802.11g /w 54 MBit/s) + * Bluetooth: 267 (100 mW @ BT2.0 EDR /w 3 MBit/s) + */ + GNUNET_TRANSPORT_ATS_COST_ENERGY_CONSUMPTION = 4, + + /** + * Connect cost + * How many bytes are transmitted to initiate a new connection using + * this transport? + * + * Unit: [bytes] + * + * Interpretation: less is better + * + * Examples: + * + * UDP (No connection) : + * 0 bytes + * TCP (TCP 3-Way handshake): + * 220 bytes Ethernet, 172 bytes TCP/IP, 122 bytes TCP + * HTTP (TCP + Header) : + * 477 bytes Ethernet, 429 bytes TCP/IP, 374 bytes TCP, 278 bytes HTTP + * HTTPS HTTP+TLS Handshake: + * 2129 bytes Ethernet, 1975 bytes TCP/IP, 1755 bytes TCP, 1403 bytes HTTPS + * + * */ + GNUNET_TRANSPORT_ATS_COST_CONNECT = 5, + + /** + * Bandwidth cost + * + * How many bandwidth is available to consume? + * Used to calculate which impact sending data with this transport has + * + * Unit: [kB/s] + * + * Interpretation: more is better + * + * Examples: + * LAN: 12,800 (100 MBit/s) + * WLAN: 6,912 (54 MBit/s) + * Dial-up: 8 (64 Kbit/s) + * + */ + GNUNET_TRANSPORT_ATS_COST_BANDWITH_AVAILABLE = 6, + + /** + * Network overhead + * + * How many bytes are sent over the wire when 1 kilobyte (1024 bytes) + * of application data is transmitted? + * A factor used with connect cost, bandwidth cost and energy cost + * to describe the overhead produced by the transport protocol + * + * Unit: [bytes/kb] + * + * Interpretation: less is better + * + * Examples: + * + * TCP/IPv4 over Ethernet: 1024 + 38 + 20 + 20 = 1102 [bytes/kb] + * TCP/IPv6 over Ethernet: 1024 + 38 + 20 + 40 = 1122 [bytes/kb] + * UDP/IPv4 over Ethernet: 1024 + 38 + 20 + 8 = 1090 [bytes/kb] + * UDP/IPv6 over Ethernet: 1024 + 38 + 40 + 8 = 1110 [bytes/kb] + */ + GNUNET_TRANSPORT_ATS_COST_NETWORK_OVERHEAD = 7, + + + /* Quality related values */ + /* ====================== */ + + /* Physical layer quality properties */ + + /** + * Signal strength on physical layer + * + * Unit: [dBm] + */ + GNUNET_TRANSPORT_ATS_QUALITY_PHY_SIGNAL_STRENGTH = 1025, + + /** + * Collision rate on physical layer + * + * Unit: [B/s] + */ + GNUNET_TRANSPORT_ATS_QUALITY_PHY_COLLISION_RATE = 1026, + + /** + * Error rate on physical layer + * + * Unit: [B/s] + */ + GNUNET_TRANSPORT_ATS_QUALITY_PHY_ERROR_RATE = 1027, + + /* Network layer quality properties */ + + /** + * Delay + * Time between when the time packet is sent and the packet arrives + * + * Unit: [μs] + * + * Examples: + * + * LAN : 180 + * Dialup: 4000 + * WLAN : 7000 + */ + GNUNET_TRANSPORT_ATS_QUALITY_NET_DELAY = 1028, + + /** + * Jitter + * Time variations of the delay + * 1st derivative of a delay function + * + * Unit: [μs] + */ + GNUNET_TRANSPORT_ATS_QUALITY_NET_JITTER = 1029, + + /** + * Error rate on network layer + * + * Unit: [B/s] + * + * Examples: + * + * LAN : 0 + * WLAN : 400 + * Bluetooth : 100 + * Note: This numbers are just assumptions as an example, not + * measured or somehow determined + */ + GNUNET_TRANSPORT_ATS_QUALITY_NET_ERRORRATE = 1030, + + /** + * Drop rate on network layer + * Bytes actively dismissed by a network component during transmission + * Reasons for dropped data can be full queues, congestion, quota violations... + * + * Unit: [B/s] + * + * Examples: + * + * LAN : 0 + * WLAN : 400 + * Bluetooth : 100 + * Note: This numbers are just assumptions as an example, not + * measured or somehow determined + */ + GNUNET_TRANSPORT_ATS_QUALITY_NET_DROPRATE = 1031, + + /** + * Loss rate on network layer + * Bytes lost during transmission + * Reasons can be collisions, ... + * + * Unit: [B/s] + * + * Examples: + * + * LAN : 0 + * WLAN : 40 + * Bluetooth : 10 + * Note: This numbers are just assumptions as an example, not measured + * or somehow determined + */ + GNUNET_TRANSPORT_ATS_QUALITY_NET_LOSSRATE = 1032, + + /** + * Throughput on network layer + * + * Unit: [kB/s] + * + * Examples: + * + * LAN : 3400 + * WLAN : 1200 + * Dialup: 4 + * + */ + GNUNET_TRANSPORT_ATS_QUALITY_NET_THROUGHPUT = 1033, + + /* Availability related values */ + /* =========================== */ + + /** + * Is a peer reachable? + */ + GNUNET_TRANSPORT_ATS_AVAILABILITY_REACHABLE = 2048, + + /** + * Is there a connection established to a peer using this transport + */ + GNUNET_TRANSPORT_ATS_AVAILABILITY_CONNECTED = 2049 + +}; + + +/** + * struct used to communicate the transport's properties like cost and + * quality of service as well as high-level constraints on resource + * consumption. + * + * +---+ + * +-----------+ Constraints | | Plugin properties +---------+ + * | Highlevel |------------> |ATS| <------------------|Transport| + * | Component | ATS struct | | ATS struct | Plugin | + * +-----------+ | | +---------+ + * +---+ + * + * This structure will be used by transport plugins to communicate + * costs to ATS or by higher level components to tell ATS their + * constraints. Always a pair of (GNUNET_TRANSPORT_ATS_Property, + * uint32_t value). Value is always uint32_t, so all units used to + * define costs have to be normalized to fit uint32_t. + */ +struct GNUNET_TRANSPORT_ATS_Information +{ + /** + * ATS property type, in network byte order. + */ + uint32_t type; + + /** + * ATS property value, in network byte order. + */ + uint32_t value; +}; + + + + /** * Function called by the transport for each received message. * diff --git a/src/testing/test_testing_topology.c b/src/testing/test_testing_topology.c index 87f90f80f..62fbc07e0 100644 --- a/src/testing/test_testing_topology.c +++ b/src/testing/test_testing_topology.c @@ -298,8 +298,6 @@ static int stats_print (void *cls, static void topology_cb (void *cls, const struct GNUNET_PeerIdentity *first, const struct GNUNET_PeerIdentity *second, - struct GNUNET_TIME_Relative latency, - uint32_t distance, const char *emsg) { FILE *outfile = cls; @@ -329,8 +327,7 @@ static int process_mtype (void *cls, const struct GNUNET_PeerIdentity *peer, const struct GNUNET_MessageHeader *message, - struct GNUNET_TIME_Relative latency, - uint32_t distance) + const struct GNUNET_TRANSPORT_ATS_Information *atsi) { char *dotOutFileNameFinished; FILE *dotOutFileFinished; @@ -522,7 +519,6 @@ init_notify_peer1 (void *cls, */ pos->peer2handle = GNUNET_CORE_connect (pos->peer2->cfg, 1, - TIMEOUT, pos, &init_notify_peer2, NULL, @@ -564,7 +560,6 @@ send_test_messages (void *cls, const struct GNUNET_SCHEDULER_TaskContext * tc) */ pos->peer1handle = GNUNET_CORE_connect (pos->peer1->cfg, 1, - TIMEOUT, pos, &init_notify_peer1, NULL, NULL, diff --git a/src/testing/testing.c b/src/testing/testing.c index d178995e0..fed3d87df 100644 --- a/src/testing/testing.c +++ b/src/testing/testing.c @@ -545,7 +545,9 @@ start_fsm (void *cls, d->phase = SP_START_CORE; d->server = GNUNET_CORE_connect (d->cfg, 1, +#if NO_MORE_TIMEOUT_FIXME ARM_START_WAIT, +#endif d, &testing_init, NULL, NULL, NULL, @@ -1347,8 +1349,15 @@ notify_connect_result (void *cls, { if (ctx->cb != NULL) { - ctx->cb (ctx->cb_cls, &ctx->d1->id, &ctx->d2->id, ctx->distance, ctx->d1->cfg, - ctx->d2->cfg, ctx->d1, ctx->d2, NULL); + ctx->cb (ctx->cb_cls, + &ctx->d1->id, + &ctx->d2->id, + ctx->distance, + ctx->d1->cfg, + ctx->d2->cfg, + ctx->d1, + ctx->d2, + NULL); } } else if (remaining.rel_value > 0) @@ -1397,25 +1406,24 @@ notify_connect_result (void *cls, * * @param cls our "struct ConnectContext" * @param peer identity of the peer that has connected - * @param latency the round trip latency of the connection to this peer - * @param distance distance the transport level distance to this peer + * @param atsi performance information * */ static void -connect_notify (void *cls, const struct GNUNET_PeerIdentity * peer, struct GNUNET_TIME_Relative latency, - uint32_t distance) +connect_notify (void *cls, + const struct GNUNET_PeerIdentity * peer, + const struct GNUNET_TRANSPORT_ATS_Information *atsi) { struct ConnectContext *ctx = cls; if (memcmp(&ctx->d2->id, peer, sizeof(struct GNUNET_PeerIdentity)) == 0) { ctx->connected = GNUNET_YES; - ctx->distance = distance; + ctx->distance = 0; /* FIXME: distance */ GNUNET_SCHEDULER_cancel(ctx->timeout_task); ctx->timeout_task = GNUNET_SCHEDULER_add_now (¬ify_connect_result, ctx); } - } #if CONNECT_CORE2 @@ -1424,20 +1432,20 @@ connect_notify (void *cls, const struct GNUNET_PeerIdentity * peer, struct GNUNE * * @param cls our "struct ConnectContext" * @param peer identity of the peer that has connected - * @param latency the round trip latency of the connection to this peer - * @param distance distance the transport level distance to this peer + * @param atsi performance information * */ static void -connect_notify_core2 (void *cls, const struct GNUNET_PeerIdentity * peer, struct GNUNET_TIME_Relative latency, - uint32_t distance) +connect_notify_core2 (void *cls, + const struct GNUNET_PeerIdentity * peer, + const struct GNUNET_TRANSPORT_ATS_Information *atsi) { struct ConnectContext *ctx = cls; if (memcmp(&ctx->d2->id, peer, sizeof(struct GNUNET_PeerIdentity)) == 0) { ctx->connected = GNUNET_YES; - ctx->distance = distance; + ctx->distance = 0; /* FIXME: distance */ GNUNET_SCHEDULER_cancel(ctx->timeout_task); ctx->timeout_task = GNUNET_SCHEDULER_add_now (¬ify_connect_result, ctx); @@ -1477,7 +1485,7 @@ send_hello(void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) GNUNET_assert(hello != NULL); GNUNET_TRANSPORT_offer_hello (ctx->d2th, hello); - ctx->connect_request_handle = GNUNET_CORE_peer_request_connect (ctx->d2->cfg, + ctx->connect_request_handle = GNUNET_CORE_peer_request_connect (ctx->d2->server, GNUNET_TIME_relative_divide(ctx->relative_timeout, ctx->max_connect_attempts + 1), &ctx->d1->id, @@ -1539,7 +1547,9 @@ GNUNET_TESTING_daemons_connect (struct GNUNET_TESTING_Daemon *d1, ctx->d1core = GNUNET_CORE_connect (d1->cfg, 1, +#if NO_MORE_TIMEOUT_FIXME timeout, +#endif ctx, NULL, &connect_notify, NULL, NULL, @@ -1557,7 +1567,9 @@ GNUNET_TESTING_daemons_connect (struct GNUNET_TESTING_Daemon *d1, #if CONNECT_CORE2 ctx->d2core = GNUNET_CORE_connect (d2->cfg, 1, +#if NO_MORE_TIMEOUT_FIXME timeout, +#endif ctx, NULL, NULL, NULL, NULL, @@ -1620,7 +1632,9 @@ reattempt_daemons_connect (void *cls, const struct GNUNET_SCHEDULER_TaskContext ctx->d1core = GNUNET_CORE_connect (ctx->d1->cfg, 1, +#if NO_MORE_TIMEOUT_FIXME GNUNET_TIME_absolute_get_remaining(ctx->timeout), +#endif ctx, NULL, &connect_notify, NULL, NULL, diff --git a/src/testing/testing_group.c b/src/testing/testing_group.c index d5a43fd37..a243a7d7c 100644 --- a/src/testing/testing_group.c +++ b/src/testing/testing_group.c @@ -3104,7 +3104,7 @@ perform_dfs (struct GNUNET_TESTING_PeerGroup *pg, unsigned int num) static void internal_topology_callback(void *cls, const struct GNUNET_PeerIdentity *peer, - struct GNUNET_TIME_Relative latency, uint32_t distance) + const struct GNUNET_TRANSPORT_ATS_Information *atsi) { struct CoreContext *core_ctx = cls; struct TopologyIterateContext *iter_ctx = core_ctx->iter_context; @@ -3118,12 +3118,14 @@ internal_topology_callback(void *cls, } else { - iter_ctx->topology_cb(iter_ctx->cls, &core_ctx->daemon->id, peer, latency, distance, NULL); + iter_ctx->topology_cb(iter_ctx->cls, &core_ctx->daemon->id, + peer, NULL); } if (iter_ctx->completed == iter_ctx->total) { - iter_ctx->topology_cb(iter_ctx->cls, NULL, NULL, GNUNET_TIME_relative_get_zero(), 0, NULL); + iter_ctx->topology_cb(iter_ctx->cls, NULL, NULL, + NULL); /* Once all are done, free the iteration context */ GNUNET_free(iter_ctx); } @@ -3157,8 +3159,8 @@ schedule_get_topology(void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) _("Creating connection, outstanding_connections is %d\n"), outstanding_connects); #endif topology_context->connected++; - if (GNUNET_OK != GNUNET_CORE_iterate_peers (core_context->daemon->cfg, &internal_topology_callback, core_context)) - internal_topology_callback(core_context, NULL, GNUNET_TIME_relative_get_zero(), 0); + if (GNUNET_OK != GNUNET_CORE_iterate_peers (core_context->daemon->server, &internal_topology_callback, core_context)) + internal_topology_callback(core_context, NULL, NULL); } } @@ -3195,7 +3197,7 @@ GNUNET_TESTING_get_topology (struct GNUNET_TESTING_PeerGroup *pg, GNUNET_TESTING } if (total_count == 0) { - cb(cls, NULL, NULL, GNUNET_TIME_relative_get_zero(), 0, "Cannot iterate over topology, no running peers!"); + cb(cls, NULL, NULL, "Cannot iterate over topology, no running peers!"); GNUNET_free(topology_context); } else diff --git a/src/topology/gnunet-daemon-topology.c b/src/topology/gnunet-daemon-topology.c index 49f460658..ef6a81882 100644 --- a/src/topology/gnunet-daemon-topology.c +++ b/src/topology/gnunet-daemon-topology.c @@ -413,7 +413,7 @@ attempt_connect (struct Peer *pos) gettext_noop ("# connect requests issued to core"), 1, GNUNET_NO); - pos->connect_req = GNUNET_CORE_peer_request_connect (cfg, + pos->connect_req = GNUNET_CORE_peer_request_connect (handle, GNUNET_TIME_UNIT_MINUTES, &pos->pid, &connect_completed_callback, @@ -689,15 +689,13 @@ reschedule_hellos (void *cls, * * @param cls closure * @param peer peer identity this notification is about - * @param latency reported latency of the connection with 'other' - * @param distance reported distance (DV) to 'other' + * @param atsi performance data */ static void connect_notify (void *cls, const struct GNUNET_PeerIdentity * peer, - struct GNUNET_TIME_Relative latency, - uint32_t distance) + const struct GNUNET_TRANSPORT_ATS_Information *atsi) { struct Peer *pos; @@ -1167,8 +1165,7 @@ read_friends_file (const struct GNUNET_CONFIGURATION_Handle *cfg) * @param other the other peer involved (sender or receiver, NULL * for loopback messages where we are both sender and receiver) * @param message the actual HELLO message - * @param latency reported latency of the connection with 'other' - * @param distance reported distance (DV) to 'other' + * @param atsi performance data * @return GNUNET_OK to keep the connection open, * GNUNET_SYSERR to close it (signal serious error) */ @@ -1177,8 +1174,7 @@ handle_encrypted_hello (void *cls, const struct GNUNET_PeerIdentity * other, const struct GNUNET_MessageHeader * message, - struct GNUNET_TIME_Relative latency, - uint32_t distance) + const struct GNUNET_TRANSPORT_ATS_Information *atsi) { struct Peer *peer; struct GNUNET_PeerIdentity pid; @@ -1379,7 +1375,6 @@ run (void *cls, NULL); handle = GNUNET_CORE_connect (cfg, 1, - GNUNET_TIME_UNIT_FOREVER_REL, NULL, &core_init, &connect_notify, -- cgit v1.2.3