diff options
author | Christian Grothoff <christian@grothoff.org> | 2014-04-11 11:49:51 +0000 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2014-04-11 11:49:51 +0000 |
commit | 24712c94e185b72c30da25ea1b3a1784bde0defa (patch) | |
tree | 1ca399a023e0cdf48dbf9b411bb4b245081a1100 /src/core/core_api_iterate_peers.c | |
parent | a61a4e0ffd7d563f3ae4d758f06a894edee71f58 (diff) | |
download | gnunet-24712c94e185b72c30da25ea1b3a1784bde0defa.tar.gz gnunet-24712c94e185b72c30da25ea1b3a1784bde0defa.zip |
towards fixing #3363: replacing old iteration API with new monitoring API for core (needs testing, gnunet-core incomplete)
Diffstat (limited to 'src/core/core_api_iterate_peers.c')
-rw-r--r-- | src/core/core_api_iterate_peers.c | 242 |
1 files changed, 155 insertions, 87 deletions
diff --git a/src/core/core_api_iterate_peers.c b/src/core/core_api_iterate_peers.c index 4889e638a..425d3579c 100644 --- a/src/core/core_api_iterate_peers.c +++ b/src/core/core_api_iterate_peers.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | This file is part of GNUnet. | 2 | This file is part of GNUnet. |
3 | (C) 2009, 2010 Christian Grothoff (and other contributing authors) | 3 | (C) 2009-2014 Christian Grothoff (and other contributing authors) |
4 | 4 | ||
5 | GNUnet is free software; you can redistribute it and/or modify | 5 | GNUnet is free software; you can redistribute it and/or modify |
6 | it under the terms of the GNU General Public License as published | 6 | it under the terms of the GNU General Public License as published |
@@ -19,7 +19,7 @@ | |||
19 | */ | 19 | */ |
20 | 20 | ||
21 | /** | 21 | /** |
22 | * @file core/core_api_iterate_peers.c | 22 | * @file core/core_api_monitor_peers.c |
23 | * @brief implementation of the peer_iterate function | 23 | * @brief implementation of the peer_iterate function |
24 | * @author Christian Grothoff | 24 | * @author Christian Grothoff |
25 | * @author Nathan Evans | 25 | * @author Nathan Evans |
@@ -29,15 +29,23 @@ | |||
29 | #include "core.h" | 29 | #include "core.h" |
30 | 30 | ||
31 | 31 | ||
32 | struct GNUNET_CORE_RequestContext | 32 | /** |
33 | * Handle to a CORE monitoring operation. | ||
34 | */ | ||
35 | struct GNUNET_CORE_MonitorHandle | ||
33 | { | 36 | { |
37 | |||
38 | /** | ||
39 | * Our configuration. | ||
40 | */ | ||
41 | const struct GNUNET_CONFIGURATION_Handle *cfg; | ||
42 | |||
34 | /** | 43 | /** |
35 | * Our connection to the service. | 44 | * Our connection to the service. |
36 | */ | 45 | */ |
37 | struct GNUNET_CLIENT_Connection *client; | 46 | struct GNUNET_CLIENT_Connection *client; |
38 | 47 | ||
39 | /** | 48 | /** |
40 | |||
41 | * Handle for transmitting a request. | 49 | * Handle for transmitting a request. |
42 | */ | 50 | */ |
43 | struct GNUNET_CLIENT_TransmitHandle *th; | 51 | struct GNUNET_CLIENT_TransmitHandle *th; |
@@ -45,140 +53,200 @@ struct GNUNET_CORE_RequestContext | |||
45 | /** | 53 | /** |
46 | * Function called with the peer. | 54 | * Function called with the peer. |
47 | */ | 55 | */ |
48 | GNUNET_CORE_ConnectEventHandler peer_cb; | 56 | GNUNET_CORE_MonitorCallback peer_cb; |
49 | 57 | ||
50 | /** | 58 | /** |
51 | * Peer to check for. | 59 | * Closure for @e peer_cb. |
52 | */ | 60 | */ |
53 | struct GNUNET_PeerIdentity *peer; | 61 | void *peer_cb_cls; |
54 | |||
55 | /** | ||
56 | * Closure for peer_cb. | ||
57 | */ | ||
58 | void *cb_cls; | ||
59 | 62 | ||
60 | }; | 63 | }; |
61 | 64 | ||
62 | 65 | ||
63 | /** | 66 | /** |
64 | * Receive reply from core service with information about a peer. | 67 | * Transmits the monitor request to the CORE service. |
68 | * | ||
69 | * Function is called to notify a client about the socket begin ready | ||
70 | * to queue more data. @a buf will be NULL and @a size zero if the | ||
71 | * socket was closed for writing in the meantime. | ||
72 | * | ||
73 | * @param cls closure, our `struct GNUNET_CORE_MonitorHandle *` | ||
74 | * @param size number of bytes available in @a buf | ||
75 | * @param buf where the callee should write the message | ||
76 | * @return number of bytes written to @a buf | ||
77 | */ | ||
78 | static size_t | ||
79 | transmit_monitor_request (void *cls, | ||
80 | size_t size, | ||
81 | void *buf); | ||
82 | |||
83 | |||
84 | /** | ||
85 | * Protocol error, reconnect to CORE service and notify | ||
86 | * client. | ||
87 | * | ||
88 | * @param mh monitoring session to reconnect to CORE | ||
89 | */ | ||
90 | static void | ||
91 | reconnect (struct GNUNET_CORE_MonitorHandle *mh) | ||
92 | { | ||
93 | GNUNET_CLIENT_disconnect (mh->client); | ||
94 | /* FIXME: use backoff? */ | ||
95 | mh->client = GNUNET_CLIENT_connect ("core", mh->cfg); | ||
96 | GNUNET_assert (NULL != mh->client); | ||
97 | mh->th = | ||
98 | GNUNET_CLIENT_notify_transmit_ready (mh->client, | ||
99 | sizeof (struct GNUNET_MessageHeader), | ||
100 | GNUNET_TIME_UNIT_FOREVER_REL, | ||
101 | GNUNET_YES, | ||
102 | &transmit_monitor_request, mh); | ||
103 | /* notify callback about reconnect */ | ||
104 | mh->peer_cb (mh->peer_cb_cls, | ||
105 | NULL, | ||
106 | GNUNET_CORE_KX_CORE_DISCONNECT, | ||
107 | GNUNET_TIME_UNIT_FOREVER_ABS); | ||
108 | } | ||
109 | |||
110 | |||
111 | /** | ||
112 | * Receive reply from CORE service with information about a peer. | ||
65 | * | 113 | * |
66 | * @param cls our 'struct GNUNET_CORE_RequestContext *' | 114 | * @param cls our `struct GNUNET_CORE_MonitorHandle *` |
67 | * @param msg NULL on error or last entry | 115 | * @param msg NULL on error or last entry |
68 | */ | 116 | */ |
69 | static void | 117 | static void |
70 | receive_info (void *cls, const struct GNUNET_MessageHeader *msg) | 118 | receive_info (void *cls, |
119 | const struct GNUNET_MessageHeader *msg) | ||
71 | { | 120 | { |
72 | struct GNUNET_CORE_RequestContext *request_context = cls; | 121 | struct GNUNET_CORE_MonitorHandle *mh = cls; |
73 | const struct ConnectNotifyMessage *connect_message; | 122 | const struct MonitorNotifyMessage *mon_message; |
74 | uint16_t msize; | 123 | uint16_t msize; |
75 | 124 | ||
76 | /* Handle last message or error case, disconnect and clean up */ | 125 | if (NULL == msg) |
77 | if ((msg == NULL) || | ||
78 | ((ntohs (msg->type) == GNUNET_MESSAGE_TYPE_CORE_ITERATE_PEERS_END) && | ||
79 | (ntohs (msg->size) == sizeof (struct GNUNET_MessageHeader)))) | ||
80 | { | 126 | { |
81 | if (request_context->peer_cb != NULL) | 127 | reconnect (mh); |
82 | request_context->peer_cb (request_context->cb_cls, NULL); | ||
83 | GNUNET_CLIENT_disconnect (request_context->client); | ||
84 | GNUNET_free (request_context); | ||
85 | return; | 128 | return; |
86 | } | 129 | } |
87 | |||
88 | msize = ntohs (msg->size); | 130 | msize = ntohs (msg->size); |
89 | /* Handle incorrect message type or size, disconnect and clean up */ | 131 | /* Handle incorrect message type or size, disconnect and clean up */ |
90 | if ((ntohs (msg->type) != GNUNET_MESSAGE_TYPE_CORE_NOTIFY_CONNECT) || | 132 | if ((ntohs (msg->type) != GNUNET_MESSAGE_TYPE_CORE_MONITOR_NOTIFY) || |
91 | (msize < sizeof (struct ConnectNotifyMessage))) | 133 | (sizeof (struct MonitorNotifyMessage) != msize)) |
92 | { | 134 | { |
93 | GNUNET_break (0); | 135 | GNUNET_break (0); |
94 | if (request_context->peer_cb != NULL) | 136 | reconnect (mh); |
95 | request_context->peer_cb (request_context->cb_cls, NULL); | ||
96 | GNUNET_CLIENT_disconnect (request_context->client); | ||
97 | GNUNET_free (request_context); | ||
98 | return; | 137 | return; |
99 | } | 138 | } |
100 | connect_message = (const struct ConnectNotifyMessage *) msg; | 139 | mon_message = (const struct MonitorNotifyMessage *) msg; |
101 | if (msize != sizeof (struct ConnectNotifyMessage)) | 140 | GNUNET_CLIENT_receive (mh->client, |
102 | { | 141 | &receive_info, mh, |
103 | GNUNET_break (0); | 142 | GNUNET_TIME_UNIT_FOREVER_REL); |
104 | if (request_context->peer_cb != NULL) | 143 | mh->peer_cb (mh->peer_cb_cls, |
105 | request_context->peer_cb (request_context->cb_cls, NULL); | 144 | &mon_message->peer, |
106 | GNUNET_CLIENT_disconnect (request_context->client); | 145 | (enum GNUNET_CORE_KxState) ntohl (mon_message->state), |
107 | GNUNET_free (request_context); | 146 | GNUNET_TIME_absolute_ntoh (mon_message->timeout)); |
108 | return; | ||
109 | } | ||
110 | /* Normal case */ | ||
111 | if (request_context->peer_cb != NULL) | ||
112 | request_context->peer_cb (request_context->cb_cls, &connect_message->peer); | ||
113 | GNUNET_CLIENT_receive (request_context->client, &receive_info, | ||
114 | request_context, GNUNET_TIME_UNIT_FOREVER_REL); | ||
115 | } | 147 | } |
116 | 148 | ||
117 | 149 | ||
118 | /** | 150 | /** |
119 | * Function called to notify a client about the socket | 151 | * Transmits the monitor request to the CORE service. |
120 | * begin ready to queue more data. "buf" will be | ||
121 | * NULL and "size" zero if the socket was closed for | ||
122 | * writing in the meantime. | ||
123 | * | 152 | * |
124 | * @param cls closure, always NULL | 153 | * Function is called to notify a client about the socket begin ready |
125 | * @param size number of bytes available in buf | 154 | * to queue more data. @a buf will be NULL and @a size zero if the |
155 | * socket was closed for writing in the meantime. | ||
156 | * | ||
157 | * @param cls closure, our `struct GNUNET_CORE_MonitorHandle *` | ||
158 | * @param size number of bytes available in @a buf | ||
126 | * @param buf where the callee should write the message | 159 | * @param buf where the callee should write the message |
127 | * @return number of bytes written to buf | 160 | * @return number of bytes written to @a buf |
128 | */ | 161 | */ |
129 | static size_t | 162 | static size_t |
130 | transmit_request (void *cls, size_t size, void *buf) | 163 | transmit_monitor_request (void *cls, |
164 | size_t size, | ||
165 | void *buf) | ||
131 | { | 166 | { |
167 | struct GNUNET_CORE_MonitorHandle *mh = cls; | ||
132 | struct GNUNET_MessageHeader *msg; | 168 | struct GNUNET_MessageHeader *msg; |
133 | int msize; | 169 | int msize; |
134 | 170 | ||
135 | msize = sizeof (struct GNUNET_MessageHeader); | 171 | msize = sizeof (struct GNUNET_MessageHeader); |
136 | if ((size < msize) || (buf == NULL)) | 172 | if ((size < msize) || (NULL == buf)) |
173 | { | ||
174 | reconnect (mh); | ||
137 | return 0; | 175 | return 0; |
176 | } | ||
138 | msg = (struct GNUNET_MessageHeader *) buf; | 177 | msg = (struct GNUNET_MessageHeader *) buf; |
139 | msg->size = htons (msize); | 178 | msg->size = htons (msize); |
140 | msg->type = htons (GNUNET_MESSAGE_TYPE_CORE_ITERATE_PEERS); | 179 | msg->type = htons (GNUNET_MESSAGE_TYPE_CORE_MONITOR_PEERS); |
141 | 180 | GNUNET_CLIENT_receive (mh->client, | |
181 | &receive_info, mh, | ||
182 | GNUNET_TIME_UNIT_FOREVER_REL); | ||
142 | return msize; | 183 | return msize; |
143 | } | 184 | } |
144 | 185 | ||
145 | 186 | ||
146 | /** | 187 | /** |
147 | * Iterate over all currently connected peers. | 188 | * Monitor connectivity and KX status of all peers known to CORE. |
148 | * Calls peer_cb with each connected peer, and then | 189 | * Calls @a peer_cb with the current status for each connected peer, |
149 | * once with NULL to indicate that all peers have | 190 | * and then once with NULL to indicate that all peers that are |
150 | * been handled. | 191 | * currently active have been handled. After that, the iteration |
192 | * continues until it is cancelled. Normal users of the CORE API are | ||
193 | * not expected to use this function. It is different in that it | ||
194 | * truly lists all connections (including those where the KX is in | ||
195 | * progress), not just those relevant to the application. This | ||
196 | * function is used by special applications for diagnostics. | ||
151 | * | 197 | * |
152 | * @param cfg configuration to use | 198 | * @param cfg configuration handle |
153 | * @param peer_cb function to call with the peer information | 199 | * @param peer_cb function to call with the peer information |
154 | * @param cb_cls closure for @a peer_cb | 200 | * @param peer_cb_cls closure for @a peer_cb |
155 | * @return #GNUNET_OK if iterating, #GNUNET_SYSERR on error | 201 | * @return NULL on error |
156 | */ | 202 | */ |
157 | int | 203 | struct GNUNET_CORE_MonitorHandle * |
158 | GNUNET_CORE_iterate_peers (const struct GNUNET_CONFIGURATION_Handle *cfg, | 204 | GNUNET_CORE_monitor_start (const struct GNUNET_CONFIGURATION_Handle *cfg, |
159 | GNUNET_CORE_ConnectEventHandler peer_cb, | 205 | GNUNET_CORE_MonitorCallback peer_cb, |
160 | void *cb_cls) | 206 | void *peer_cb_cls) |
161 | { | 207 | { |
162 | struct GNUNET_CORE_RequestContext *request_context; | 208 | struct GNUNET_CORE_MonitorHandle *mh; |
163 | struct GNUNET_CLIENT_Connection *client; | 209 | struct GNUNET_CLIENT_Connection *client; |
164 | 210 | ||
211 | GNUNET_assert (NULL != peer_cb); | ||
165 | client = GNUNET_CLIENT_connect ("core", cfg); | 212 | client = GNUNET_CLIENT_connect ("core", cfg); |
166 | if (client == NULL) | 213 | if (NULL == client) |
167 | return GNUNET_SYSERR; | 214 | return NULL; |
168 | request_context = GNUNET_new (struct GNUNET_CORE_RequestContext); | 215 | mh = GNUNET_new (struct GNUNET_CORE_MonitorHandle); |
169 | request_context->client = client; | 216 | mh->cfg = cfg; |
170 | request_context->peer_cb = peer_cb; | 217 | mh->client = client; |
171 | request_context->cb_cls = cb_cls; | 218 | mh->peer_cb = peer_cb; |
172 | 219 | mh->peer_cb_cls = peer_cb_cls; | |
173 | request_context->th = | 220 | mh->th = |
174 | GNUNET_CLIENT_notify_transmit_ready (client, | 221 | GNUNET_CLIENT_notify_transmit_ready (client, |
175 | sizeof (struct GNUNET_MessageHeader), | 222 | sizeof (struct GNUNET_MessageHeader), |
176 | GNUNET_TIME_UNIT_FOREVER_REL, | 223 | GNUNET_TIME_UNIT_FOREVER_REL, |
177 | GNUNET_YES, &transmit_request, NULL); | 224 | GNUNET_YES, |
178 | 225 | &transmit_monitor_request, mh); | |
179 | GNUNET_CLIENT_receive (client, &receive_info, request_context, | 226 | return mh; |
180 | GNUNET_TIME_UNIT_FOREVER_REL); | ||
181 | return GNUNET_OK; | ||
182 | } | 227 | } |
183 | 228 | ||
184 | /* end of core_api_iterate_peers.c */ | 229 | |
230 | /** | ||
231 | * Stop monitoring CORE activity. | ||
232 | * | ||
233 | * @param mh monitor to stop | ||
234 | */ | ||
235 | void | ||
236 | GNUNET_CORE_monitor_stop (struct GNUNET_CORE_MonitorHandle *mh) | ||
237 | { | ||
238 | if (NULL != mh->th) | ||
239 | { | ||
240 | GNUNET_CLIENT_notify_transmit_ready_cancel (mh->th); | ||
241 | mh->th = NULL; | ||
242 | } | ||
243 | if (NULL != mh->client) | ||
244 | { | ||
245 | GNUNET_CLIENT_disconnect (mh->client); | ||
246 | mh->client = NULL; | ||
247 | } | ||
248 | GNUNET_free (mh); | ||
249 | } | ||
250 | |||
251 | |||
252 | /* end of core_api_monitor_peers.c */ | ||