aboutsummaryrefslogtreecommitdiff
path: root/src/core
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2014-04-11 11:49:51 +0000
committerChristian Grothoff <christian@grothoff.org>2014-04-11 11:49:51 +0000
commit24712c94e185b72c30da25ea1b3a1784bde0defa (patch)
tree1ca399a023e0cdf48dbf9b411bb4b245081a1100 /src/core
parenta61a4e0ffd7d563f3ae4d758f06a894edee71f58 (diff)
downloadgnunet-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')
-rw-r--r--src/core/core.h41
-rw-r--r--src/core/core_api_iterate_peers.c242
-rw-r--r--src/core/gnunet-core.c186
-rw-r--r--src/core/gnunet-service-core.c15
-rw-r--r--src/core/gnunet-service-core_clients.c12
-rw-r--r--src/core/gnunet-service-core_kx.c268
-rw-r--r--src/core/gnunet-service-core_kx.h21
-rw-r--r--src/core/gnunet-service-core_sessions.c53
-rw-r--r--src/core/gnunet-service-core_sessions.h17
9 files changed, 455 insertions, 400 deletions
diff --git a/src/core/core.h b/src/core/core.h
index 1c6e0bc72..fba9ad1f3 100644
--- a/src/core/core.h
+++ b/src/core/core.h
@@ -62,7 +62,7 @@ struct InitMessage
62{ 62{
63 63
64 /** 64 /**
65 * Header with type GNUNET_MESSAGE_TYPE_CORE_INIT. 65 * Header with type #GNUNET_MESSAGE_TYPE_CORE_INIT.
66 */ 66 */
67 struct GNUNET_MessageHeader header; 67 struct GNUNET_MessageHeader header;
68 68
@@ -82,7 +82,7 @@ struct InitReplyMessage
82{ 82{
83 83
84 /** 84 /**
85 * Header with type GNUNET_MESSAGE_TYPE_CORE_INIT_REPLY 85 * Header with type #GNUNET_MESSAGE_TYPE_CORE_INIT_REPLY
86 */ 86 */
87 struct GNUNET_MessageHeader header; 87 struct GNUNET_MessageHeader header;
88 88
@@ -106,7 +106,7 @@ struct InitReplyMessage
106struct ConnectNotifyMessage 106struct ConnectNotifyMessage
107{ 107{
108 /** 108 /**
109 * Header with type GNUNET_MESSAGE_TYPE_CORE_NOTIFY_CONNECT 109 * Header with type #GNUNET_MESSAGE_TYPE_CORE_NOTIFY_CONNECT
110 */ 110 */
111 struct GNUNET_MessageHeader header; 111 struct GNUNET_MessageHeader header;
112 112
@@ -130,7 +130,7 @@ struct ConnectNotifyMessage
130struct DisconnectNotifyMessage 130struct DisconnectNotifyMessage
131{ 131{
132 /** 132 /**
133 * Header with type GNUNET_MESSAGE_TYPE_CORE_NOTIFY_DISCONNECT. 133 * Header with type #GNUNET_MESSAGE_TYPE_CORE_NOTIFY_DISCONNECT.
134 */ 134 */
135 struct GNUNET_MessageHeader header; 135 struct GNUNET_MessageHeader header;
136 136
@@ -159,8 +159,8 @@ struct DisconnectNotifyMessage
159struct NotifyTrafficMessage 159struct NotifyTrafficMessage
160{ 160{
161 /** 161 /**
162 * Header with type GNUNET_MESSAGE_TYPE_CORE_NOTIFY_INBOUND 162 * Header with type #GNUNET_MESSAGE_TYPE_CORE_NOTIFY_INBOUND
163 * or GNUNET_MESSAGE_TYPE_CORE_NOTIFY_OUTBOUND. 163 * or #GNUNET_MESSAGE_TYPE_CORE_NOTIFY_OUTBOUND.
164 */ 164 */
165 struct GNUNET_MessageHeader header; 165 struct GNUNET_MessageHeader header;
166 166
@@ -291,6 +291,35 @@ struct SendMessage
291}; 291};
292 292
293 293
294/**
295 * Message sent by the service to monitor clients to notify them
296 * about a peer changing status.
297 */
298struct MonitorNotifyMessage
299{
300 /**
301 * Header with type #GNUNET_MESSAGE_TYPE_CORE_MONITOR_NOTIFY
302 */
303 struct GNUNET_MessageHeader header;
304
305 /**
306 * New peer state, an `enum GNUNET_CORE_KxState` in NBO.
307 */
308 uint32_t state GNUNET_PACKED;
309
310 /**
311 * Identity of the peer.
312 */
313 struct GNUNET_PeerIdentity peer;
314
315 /**
316 * How long will we stay in this state (if nothing else happens)?
317 */
318 struct GNUNET_TIME_AbsoluteNBO timeout;
319
320};
321
322
294GNUNET_NETWORK_STRUCT_END 323GNUNET_NETWORK_STRUCT_END
295#endif 324#endif
296/* end of core.h */ 325/* end of core.h */
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
32struct GNUNET_CORE_RequestContext 32/**
33 * Handle to a CORE monitoring operation.
34 */
35struct 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 */
78static size_t
79transmit_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 */
90static void
91reconnect (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 */
69static void 117static void
70receive_info (void *cls, const struct GNUNET_MessageHeader *msg) 118receive_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 */
129static size_t 162static size_t
130transmit_request (void *cls, size_t size, void *buf) 163transmit_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 */
157int 203struct GNUNET_CORE_MonitorHandle *
158GNUNET_CORE_iterate_peers (const struct GNUNET_CONFIGURATION_Handle *cfg, 204GNUNET_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 */
235void
236GNUNET_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 */
diff --git a/src/core/gnunet-core.c b/src/core/gnunet-core.c
index 6309b39e0..36dc5fc6f 100644
--- a/src/core/gnunet-core.c
+++ b/src/core/gnunet-core.c
@@ -1,6 +1,6 @@
1/* 1/*
2 This file is part of GNUnet. 2 This file is part of GNUnet.
3 (C) 2011, 2012 Christian Grothoff (and other contributing authors) 3 (C) 2011, 2012, 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
@@ -24,13 +24,9 @@
24 * @author Nathan Evans 24 * @author Nathan Evans
25 */ 25 */
26#include "platform.h" 26#include "platform.h"
27#include "gnunet_crypto_lib.h" 27#include "gnunet_util_lib.h"
28#include "gnunet_configuration_lib.h"
29#include "gnunet_getopt_lib.h"
30#include "gnunet_peerinfo_service.h"
31#include "gnunet_transport_service.h"
32#include "gnunet_core_service.h" 28#include "gnunet_core_service.h"
33#include "gnunet_program_lib.h" 29
34 30
35/** 31/**
36 * Option -m. 32 * Option -m.
@@ -40,11 +36,13 @@ static int monitor_connections;
40/** 36/**
41 * Current number of connections in monitor mode 37 * Current number of connections in monitor mode
42 */ 38 */
43static int monitor_connections_counter; 39// static unsigned int monitor_connections_counter;
44 40
45static struct GNUNET_CORE_Handle *ch; 41/**
42 * Handle to the CORE monitor.
43 */
44static struct GNUNET_CORE_MonitorHandle *mh;
46 45
47static struct GNUNET_PeerIdentity my_id;
48 46
49/** 47/**
50 * Task run in monitor mode when the user presses CTRL-C to abort. 48 * Task run in monitor mode when the user presses CTRL-C to abort.
@@ -57,143 +55,81 @@ static void
57shutdown_task (void *cls, 55shutdown_task (void *cls,
58 const struct GNUNET_SCHEDULER_TaskContext *tc) 56 const struct GNUNET_SCHEDULER_TaskContext *tc)
59{ 57{
60 if (NULL != ch) 58 if (NULL != mh)
61 { 59 {
62 GNUNET_CORE_disconnect (ch); 60 GNUNET_CORE_monitor_stop (mh);
63 ch = NULL; 61 mh = NULL;
64 } 62 }
65} 63}
66 64
67 65
68/** 66/**
69 * Callback for retrieving a list of connected peers.
70 *
71 * @param cls closure (unused)
72 * @param peer peer identity this notification is about
73 */
74static void
75connected_peer_callback (void *cls,
76 const struct GNUNET_PeerIdentity *peer)
77{
78 if (NULL == peer)
79 return;
80 printf (_("Peer `%s'\n"),
81 GNUNET_i2s_full (peer));
82}
83
84
85static void
86monitor_notify_startup (void *cls,
87 const struct GNUNET_PeerIdentity *my_identity)
88{
89 my_id = (*my_identity);
90}
91
92
93/**
94 * Function called to notify core users that another 67 * Function called to notify core users that another
95 * peer connected to us. 68 * peer changed its state with us.
96 * 69 *
97 * @param cls closure 70 * @param cls closure
98 * @param peer the peer that connected 71 * @param peer the peer that changed state
72 * @param state new state of the peer
73 * @param timeout timeout for the new state
99 */ 74 */
100static void 75static void
101monitor_notify_connect (void *cls, const struct GNUNET_PeerIdentity *peer) 76monitor_cb (void *cls,
77 const struct GNUNET_PeerIdentity *peer,
78 enum GNUNET_CORE_KxState state,
79 struct GNUNET_TIME_Absolute timeout)
102{ 80{
103 struct GNUNET_TIME_Absolute now = GNUNET_TIME_absolute_get(); 81 struct GNUNET_TIME_Absolute now = GNUNET_TIME_absolute_get();
104 const char *now_str; 82 const char *now_str;
105 83
106 if (0 != memcmp (&my_id, peer, sizeof (my_id))) 84 if ( (NULL == peer) &&
85 (GNUNET_NO == monitor_connections) )
107 { 86 {
108 monitor_connections_counter ++; 87 GNUNET_SCHEDULER_shutdown ();
109 now_str = GNUNET_STRINGS_absolute_time_to_string (now); 88 return;
110 FPRINTF (stdout, _("%24s: %-17s %4s (%u connections in total)\n"),
111 now_str,
112 _("Connected to"),
113 GNUNET_i2s (peer),
114 monitor_connections_counter);
115 } 89 }
90 now_str = GNUNET_STRINGS_absolute_time_to_string (now);
91 FPRINTF (stdout,
92 _("%24s: %-17s %d %4s\n"),
93 now_str,
94 "FIXME",
95 state,
96 GNUNET_i2s (peer));
116} 97}
117 98
118 99
119/** 100/**
120 * Function called to notify core users that another 101 * Function called with the result of the check if the CORE
121 * peer disconnected from us.
122 *
123 * @param cls closure
124 * @param peer the peer that disconnected
125 */
126static void
127monitor_notify_disconnect (void *cls, const struct GNUNET_PeerIdentity *peer)
128{
129 struct GNUNET_TIME_Absolute now = GNUNET_TIME_absolute_get();
130 const char *now_str;
131
132 if (0 != memcmp (&my_id, peer, sizeof (my_id)))
133 {
134 now_str = GNUNET_STRINGS_absolute_time_to_string (now);
135
136 GNUNET_assert (monitor_connections_counter > 0);
137 monitor_connections_counter--;
138 FPRINTF (stdout, _("%24s: %-17s %4s (%u connections in total)\n"),
139 now_str,
140 _("Disconnected from"),
141 GNUNET_i2s (peer),
142 monitor_connections_counter);
143 }
144}
145
146/**
147 * Function called with the result of the check if the 'transport'
148 * service is running. 102 * service is running.
149 * 103 *
150 * @param cls closure with our configuration 104 * @param cls closure with our configuration
151 * @param result #GNUNET_YES if transport is running 105 * @param result #GNUNET_YES if CORE is running
152 */ 106 */
153static void 107static void
154testservice_task (void *cls, int result) 108testservice_task (void *cls,
109 int result)
155{ 110{
156 const struct GNUNET_CONFIGURATION_Handle *cfg = cls; 111 const struct GNUNET_CONFIGURATION_Handle *cfg = cls;
157 static const struct GNUNET_CORE_MessageHandler handlers[] = {
158 {NULL, 0, 0}
159 };
160
161 if (result != GNUNET_OK)
162 {
163 FPRINTF (stderr, _("Service `%s' is not running\n"), "core");
164 return;
165 }
166 112
167 if (GNUNET_NO == monitor_connections) 113 if (GNUNET_OK != result)
168 { 114 {
169 if (GNUNET_OK != GNUNET_CORE_iterate_peers (cfg, &connected_peer_callback, NULL)) 115 FPRINTF (stderr, _("Service `%s' is not running\n"), "core");
170 { 116 return;
171 fprintf (stderr, ("Failed to connect to CORE service to iterate peers!\n"));
172 return;
173 }
174 } 117 }
175 else 118
119 mh = GNUNET_CORE_monitor_start (cfg,
120 &monitor_cb,
121 NULL);
122 if (NULL == mh)
176 { 123 {
177 memset(&my_id, '\0', sizeof (my_id)); 124 GNUNET_SCHEDULER_add_now (shutdown_task, NULL);
178 ch = GNUNET_CORE_connect (cfg, NULL, 125 fprintf (stderr, ("Failed to connect to CORE service!\n"));
179 monitor_notify_startup, 126 return;
180 monitor_notify_connect,
181 monitor_notify_disconnect,
182 NULL, GNUNET_NO,
183 NULL, GNUNET_NO,
184 handlers);
185
186 if (NULL == ch)
187 {
188 GNUNET_SCHEDULER_add_now (shutdown_task, NULL);
189 fprintf (stderr, ("Failed to connect to CORE service!\n"));
190 return;
191 }
192 else
193 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, shutdown_task, NULL);
194 } 127 }
128 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL,
129 &shutdown_task, NULL);
195} 130}
196 131
132
197/** 133/**
198 * Main function that will be run by the scheduler. 134 * Main function that will be run by the scheduler.
199 * 135 *
@@ -206,19 +142,21 @@ static void
206run (void *cls, char *const *args, const char *cfgfile, 142run (void *cls, char *const *args, const char *cfgfile,
207 const struct GNUNET_CONFIGURATION_Handle *cfg) 143 const struct GNUNET_CONFIGURATION_Handle *cfg)
208{ 144{
209 if (args[0] != NULL) 145 if (NULL != args[0])
210 { 146 {
211 FPRINTF (stderr, _("Invalid command line argument `%s'\n"), args[0]); 147 FPRINTF (stderr,
148 _("Invalid command line argument `%s'\n"),
149 args[0]);
212 return; 150 return;
213 } 151 }
214 152 GNUNET_CLIENT_service_test ("core", cfg,
215 GNUNET_CLIENT_service_test ("core", cfg, GNUNET_TIME_UNIT_SECONDS, 153 GNUNET_TIME_UNIT_SECONDS,
216 &testservice_task, (void *) cfg); 154 &testservice_task, (void *) cfg);
217} 155}
218 156
219 157
220/** 158/**
221 * The main function to obtain peer information. 159 * The main function to obtain peer information from CORE.
222 * 160 *
223 * @param argc number of arguments from the command line 161 * @param argc number of arguments from the command line
224 * @param argv command line arguments 162 * @param argv command line arguments
@@ -237,19 +175,15 @@ main (int argc, char *const *argv)
237 175
238 if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv)) 176 if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv))
239 return 2; 177 return 2;
240
241
242 res = GNUNET_PROGRAM_run (argc, argv, "gnunet-core", 178 res = GNUNET_PROGRAM_run (argc, argv, "gnunet-core",
243 gettext_noop 179 gettext_noop
244 ("Print information about connected peers."), 180 ("Print information about connected peers."),
245 options, &run, NULL); 181 options, &run, NULL);
246 182
247 GNUNET_free ((void *) argv); 183 GNUNET_free ((void *) argv);
248
249 if (GNUNET_OK == res) 184 if (GNUNET_OK == res)
250 return 0; 185 return 0;
251 else 186 return 1;
252 return 1;
253} 187}
254 188
255/* end of gnunet-core.c */ 189/* end of gnunet-core.c */
diff --git a/src/core/gnunet-service-core.c b/src/core/gnunet-service-core.c
index c6eeb070b..05e461278 100644
--- a/src/core/gnunet-service-core.c
+++ b/src/core/gnunet-service-core.c
@@ -101,20 +101,21 @@ run (void *cls, struct GNUNET_SERVER_Handle *server,
101 &keyfile)) 101 &keyfile))
102 { 102 {
103 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 103 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
104 _ 104 _("Core service is lacking HOSTKEY configuration setting. Exiting.\n"));
105 ("Core service is lacking HOSTKEY configuration setting. Exiting.\n"));
106 GNUNET_SCHEDULER_shutdown (); 105 GNUNET_SCHEDULER_shutdown ();
107 return; 106 return;
108 } 107 }
109 GSC_stats = GNUNET_STATISTICS_create ("core", GSC_cfg); 108 GSC_stats = GNUNET_STATISTICS_create ("core", GSC_cfg);
110 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &shutdown_task, 109 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL,
110 &shutdown_task,
111 NULL); 111 NULL);
112 GNUNET_SERVER_suspend (server); 112 GNUNET_SERVER_suspend (server);
113 GSC_TYPEMAP_init (); 113 GSC_TYPEMAP_init ();
114 pk = GNUNET_CRYPTO_eddsa_key_create_from_file (keyfile); 114 pk = GNUNET_CRYPTO_eddsa_key_create_from_file (keyfile);
115 GNUNET_free (keyfile); 115 GNUNET_free (keyfile);
116 GNUNET_assert (NULL != pk); 116 GNUNET_assert (NULL != pk);
117 if ((GNUNET_OK != GSC_KX_init (pk)) || 117 if ((GNUNET_OK != GSC_KX_init (pk,
118 server)) ||
118 (GNUNET_OK != GSC_NEIGHBOURS_init ())) 119 (GNUNET_OK != GSC_NEIGHBOURS_init ()))
119 { 120 {
120 GNUNET_SCHEDULER_shutdown (); 121 GNUNET_SCHEDULER_shutdown ();
@@ -123,7 +124,8 @@ run (void *cls, struct GNUNET_SERVER_Handle *server,
123 GSC_SESSIONS_init (); 124 GSC_SESSIONS_init ();
124 GSC_CLIENTS_init (GSC_server); 125 GSC_CLIENTS_init (GSC_server);
125 GNUNET_SERVER_resume (GSC_server); 126 GNUNET_SERVER_resume (GSC_server);
126 GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Core service of `%4s' ready.\n"), 127 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
128 _("Core service of `%4s' ready.\n"),
127 GNUNET_i2s (&GSC_my_identity)); 129 GNUNET_i2s (&GSC_my_identity));
128} 130}
129 131
@@ -139,7 +141,8 @@ int
139main (int argc, char *const *argv) 141main (int argc, char *const *argv)
140{ 142{
141 return (GNUNET_OK == 143 return (GNUNET_OK ==
142 GNUNET_SERVICE_run (argc, argv, "core", GNUNET_SERVICE_OPTION_NONE, 144 GNUNET_SERVICE_run (argc, argv, "core",
145 GNUNET_SERVICE_OPTION_NONE,
143 &run, NULL)) ? 0 : 1; 146 &run, NULL)) ? 0 : 1;
144} 147}
145 148
diff --git a/src/core/gnunet-service-core_clients.c b/src/core/gnunet-service-core_clients.c
index 5a30138a0..634959674 100644
--- a/src/core/gnunet-service-core_clients.c
+++ b/src/core/gnunet-service-core_clients.c
@@ -600,11 +600,12 @@ destroy_active_client_request (void *cls,
600 * @param client identification of the client 600 * @param client identification of the client
601 */ 601 */
602static void 602static void
603handle_client_disconnect (void *cls, struct GNUNET_SERVER_Client *client) 603handle_client_disconnect (void *cls,
604 struct GNUNET_SERVER_Client *client)
604{ 605{
605 struct GSC_Client *c; 606 struct GSC_Client *c;
606 607
607 if (client == NULL) 608 if (NULL == client)
608 return; 609 return;
609 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 610 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
610 "Client %p has disconnected from core service.\n", client); 611 "Client %p has disconnected from core service.\n", client);
@@ -840,8 +841,8 @@ GSC_CLIENTS_init (struct GNUNET_SERVER_Handle *server)
840 static const struct GNUNET_SERVER_MessageHandler handlers[] = { 841 static const struct GNUNET_SERVER_MessageHandler handlers[] = {
841 {&handle_client_init, NULL, 842 {&handle_client_init, NULL,
842 GNUNET_MESSAGE_TYPE_CORE_INIT, 0}, 843 GNUNET_MESSAGE_TYPE_CORE_INIT, 0},
843 {&GSC_SESSIONS_handle_client_iterate_peers, NULL, 844 {&GSC_KX_handle_client_monitor_peers, NULL,
844 GNUNET_MESSAGE_TYPE_CORE_ITERATE_PEERS, 845 GNUNET_MESSAGE_TYPE_CORE_MONITOR_PEERS,
845 sizeof (struct GNUNET_MessageHeader)}, 846 sizeof (struct GNUNET_MessageHeader)},
846 {&handle_client_send_request, NULL, 847 {&handle_client_send_request, NULL,
847 GNUNET_MESSAGE_TYPE_CORE_SEND_REQUEST, 848 GNUNET_MESSAGE_TYPE_CORE_SEND_REQUEST,
@@ -855,7 +856,8 @@ GSC_CLIENTS_init (struct GNUNET_SERVER_Handle *server)
855 client_mst = GNUNET_SERVER_mst_create (&client_tokenizer_callback, NULL); 856 client_mst = GNUNET_SERVER_mst_create (&client_tokenizer_callback, NULL);
856 notifier = 857 notifier =
857 GNUNET_SERVER_notification_context_create (server, MAX_NOTIFY_QUEUE); 858 GNUNET_SERVER_notification_context_create (server, MAX_NOTIFY_QUEUE);
858 GNUNET_SERVER_disconnect_notify (server, &handle_client_disconnect, NULL); 859 GNUNET_SERVER_disconnect_notify (server,
860 &handle_client_disconnect, NULL);
859 GNUNET_SERVER_add_handlers (server, handlers); 861 GNUNET_SERVER_add_handlers (server, handlers);
860} 862}
861 863
diff --git a/src/core/gnunet-service-core_kx.c b/src/core/gnunet-service-core_kx.c
index 4a516461f..4ab902fbe 100644
--- a/src/core/gnunet-service-core_kx.c
+++ b/src/core/gnunet-service-core_kx.c
@@ -237,50 +237,6 @@ GNUNET_NETWORK_STRUCT_END
237 237
238 238
239/** 239/**
240 * State machine for our P2P encryption handshake. Everyone starts in
241 * "DOWN", if we receive the other peer's key (other peer initiated)
242 * we start in state RECEIVED (since we will immediately send our
243 * own); otherwise we start in SENT. If we get back a PONG from
244 * within either state, we move up to CONFIRMED (the PONG will always
245 * be sent back encrypted with the key we sent to the other peer).
246 */
247enum KxStateMachine
248{
249 /**
250 * No handshake yet.
251 */
252 KX_STATE_DOWN,
253
254 /**
255 * We've sent our session key.
256 */
257 KX_STATE_KEY_SENT,
258
259 /**
260 * We've received the other peers session key.
261 */
262 KX_STATE_KEY_RECEIVED,
263
264 /**
265 * The other peer has confirmed our session key + PING with a PONG
266 * message encrypted with his session key (which we got). Key
267 * exchange is done.
268 */
269 KX_STATE_UP,
270
271 /**
272 * We're rekeying (or had a timeout), so we have sent the other peer
273 * our new ephemeral key, but we did not get a matching PONG yet.
274 * This is equivalent to being 'KX_STATE_KEY_RECEIVED', except that
275 * the session is marked as 'up' with sessions (as we don't want to
276 * drop and re-establish P2P connections simply due to rekeying).
277 */
278 KX_STATE_REKEY_SENT
279
280};
281
282
283/**
284 * Information about the status of a key exchange with another peer. 240 * Information about the status of a key exchange with another peer.
285 */ 241 */
286struct GSC_KeyExchangeInfo 242struct GSC_KeyExchangeInfo
@@ -373,7 +329,7 @@ struct GSC_KeyExchangeInfo
373 /** 329 /**
374 * What is our connection status? 330 * What is our connection status?
375 */ 331 */
376 enum KxStateMachine status; 332 enum GNUNET_CORE_KxState status;
377 333
378}; 334};
379 335
@@ -414,6 +370,57 @@ static struct GSC_KeyExchangeInfo *kx_tail;
414 */ 370 */
415static GNUNET_SCHEDULER_TaskIdentifier rekey_task; 371static GNUNET_SCHEDULER_TaskIdentifier rekey_task;
416 372
373/**
374 * Notification context for all monitors.
375 */
376static struct GNUNET_SERVER_NotificationContext *nc;
377
378
379/**
380 * Inform the given monitor about the KX state of
381 * the given peer.
382 *
383 * @param mc monitor to inform
384 * @param kx key exchange state to inform about
385 */
386static void
387monitor_notify (struct GNUNET_SERVER_Client *client,
388 struct GSC_KeyExchangeInfo *kx)
389{
390 struct MonitorNotifyMessage msg;
391
392 msg.header.type = htons (GNUNET_MESSAGE_TYPE_CORE_MONITOR_NOTIFY);
393 msg.header.size = htons (sizeof (msg));
394 msg.state = htonl ((uint32_t) kx->status);
395 msg.peer = kx->peer;
396 msg.timeout = GNUNET_TIME_absolute_hton (kx->timeout);
397 GNUNET_SERVER_notification_context_unicast (nc,
398 client,
399 &msg.header,
400 GNUNET_NO);
401}
402
403
404/**
405 * Inform all monitors about the KX state of the given peer.
406 *
407 * @param kx key exchange state to inform about
408 */
409static void
410monitor_notify_all (struct GSC_KeyExchangeInfo *kx)
411{
412 struct MonitorNotifyMessage msg;
413
414 msg.header.type = htons (GNUNET_MESSAGE_TYPE_CORE_MONITOR_NOTIFY);
415 msg.header.size = htons (sizeof (msg));
416 msg.state = htonl ((uint32_t) kx->status);
417 msg.peer = kx->peer;
418 msg.timeout = GNUNET_TIME_absolute_hton (kx->timeout);
419 GNUNET_SERVER_notification_context_broadcast (nc,
420 &msg.header,
421 GNUNET_NO);
422}
423
417 424
418/** 425/**
419 * Derive an authentication key from "set key" information 426 * Derive an authentication key from "set key" information
@@ -570,8 +577,9 @@ do_decrypt (struct GSC_KeyExchangeInfo *kx,
570 GNUNET_break (0); 577 GNUNET_break (0);
571 return GNUNET_NO; 578 return GNUNET_NO;
572 } 579 }
573 if ( (kx->status != KX_STATE_KEY_RECEIVED) && (kx->status != KX_STATE_UP) && 580 if ( (kx->status != GNUNET_CORE_KX_STATE_KEY_RECEIVED) &&
574 (kx->status != KX_STATE_REKEY_SENT) ) 581 (kx->status != GNUNET_CORE_KX_STATE_UP) &&
582 (kx->status != GNUNET_CORE_KX_STATE_REKEY_SENT) )
575 { 583 {
576 GNUNET_break_op (0); 584 GNUNET_break_op (0);
577 return GNUNET_SYSERR; 585 return GNUNET_SYSERR;
@@ -622,7 +630,7 @@ set_key_retry_task (void *cls,
622 630
623 kx->retry_set_key_task = GNUNET_SCHEDULER_NO_TASK; 631 kx->retry_set_key_task = GNUNET_SCHEDULER_NO_TASK;
624 kx->set_key_retry_frequency = GNUNET_TIME_STD_BACKOFF (kx->set_key_retry_frequency); 632 kx->set_key_retry_frequency = GNUNET_TIME_STD_BACKOFF (kx->set_key_retry_frequency);
625 GNUNET_assert (KX_STATE_DOWN != kx->status); 633 GNUNET_assert (GNUNET_CORE_KX_STATE_DOWN != kx->status);
626 send_key (kx); 634 send_key (kx);
627} 635}
628 636
@@ -678,10 +686,14 @@ GSC_KX_start (const struct GNUNET_PeerIdentity *pid)
678 GNUNET_CONTAINER_DLL_insert (kx_head, 686 GNUNET_CONTAINER_DLL_insert (kx_head,
679 kx_tail, 687 kx_tail,
680 kx); 688 kx);
681 GNUNET_CRYPTO_hash (pid, sizeof (struct GNUNET_PeerIdentity), &h1); 689 kx->status = GNUNET_CORE_KX_STATE_KEY_SENT;
682 GNUNET_CRYPTO_hash (&GSC_my_identity, sizeof (struct GNUNET_PeerIdentity), &h2); 690 monitor_notify_all (kx);
683 691 GNUNET_CRYPTO_hash (pid,
684 kx->status = KX_STATE_KEY_SENT; 692 sizeof (struct GNUNET_PeerIdentity),
693 &h1);
694 GNUNET_CRYPTO_hash (&GSC_my_identity,
695 sizeof (struct GNUNET_PeerIdentity),
696 &h2);
685 if (0 < GNUNET_CRYPTO_hash_cmp (&h1, 697 if (0 < GNUNET_CRYPTO_hash_cmp (&h1,
686 &h2)) 698 &h2))
687 { 699 {
@@ -722,6 +734,8 @@ GSC_KX_stop (struct GSC_KeyExchangeInfo *kx)
722 GNUNET_SCHEDULER_cancel (kx->keep_alive_task); 734 GNUNET_SCHEDULER_cancel (kx->keep_alive_task);
723 kx->keep_alive_task = GNUNET_SCHEDULER_NO_TASK; 735 kx->keep_alive_task = GNUNET_SCHEDULER_NO_TASK;
724 } 736 }
737 kx->status = GNUNET_CORE_KX_PEER_DISCONNECT;
738 monitor_notify_all (kx);
725 GNUNET_CONTAINER_DLL_remove (kx_head, 739 GNUNET_CONTAINER_DLL_remove (kx_head,
726 kx_tail, 740 kx_tail,
727 kx); 741 kx);
@@ -791,7 +805,7 @@ GSC_KX_handle_ephemeral_key (struct GSC_KeyExchangeInfo *kx,
791 struct GNUNET_TIME_Absolute start_t; 805 struct GNUNET_TIME_Absolute start_t;
792 struct GNUNET_TIME_Absolute end_t; 806 struct GNUNET_TIME_Absolute end_t;
793 struct GNUNET_TIME_Absolute now; 807 struct GNUNET_TIME_Absolute now;
794 enum KxStateMachine sender_status; 808 enum GNUNET_CORE_KxState sender_status;
795 uint16_t size; 809 uint16_t size;
796 810
797 size = ntohs (msg->size); 811 size = ntohs (msg->size);
@@ -802,9 +816,9 @@ GSC_KX_handle_ephemeral_key (struct GSC_KeyExchangeInfo *kx,
802 } 816 }
803 m = (const struct EphemeralKeyMessage *) msg; 817 m = (const struct EphemeralKeyMessage *) msg;
804 end_t = GNUNET_TIME_absolute_ntoh (m->expiration_time); 818 end_t = GNUNET_TIME_absolute_ntoh (m->expiration_time);
805 if ( ( (KX_STATE_KEY_RECEIVED == kx->status) || 819 if ( ( (GNUNET_CORE_KX_STATE_KEY_RECEIVED == kx->status) ||
806 (KX_STATE_UP == kx->status) || 820 (GNUNET_CORE_KX_STATE_UP == kx->status) ||
807 (KX_STATE_REKEY_SENT == kx->status) ) && 821 (GNUNET_CORE_KX_STATE_REKEY_SENT == kx->status) ) &&
808 (end_t.abs_value_us <= kx->foreign_key_expires.abs_value_us) ) 822 (end_t.abs_value_us <= kx->foreign_key_expires.abs_value_us) )
809 { 823 {
810 GNUNET_STATISTICS_update (GSC_stats, gettext_noop ("# old ephemeral keys ignored"), 824 GNUNET_STATISTICS_update (GSC_stats, gettext_noop ("# old ephemeral keys ignored"),
@@ -862,18 +876,18 @@ GSC_KX_handle_ephemeral_key (struct GSC_KeyExchangeInfo *kx,
862 GNUNET_NO); 876 GNUNET_NO);
863 877
864 /* check if we still need to send the sender our key */ 878 /* check if we still need to send the sender our key */
865 sender_status = (enum KxStateMachine) ntohl (m->sender_status); 879 sender_status = (enum GNUNET_CORE_KxState) ntohl (m->sender_status);
866 switch (sender_status) 880 switch (sender_status)
867 { 881 {
868 case KX_STATE_DOWN: 882 case GNUNET_CORE_KX_STATE_DOWN:
869 GNUNET_break_op (0); 883 GNUNET_break_op (0);
870 break; 884 break;
871 case KX_STATE_KEY_SENT: 885 case GNUNET_CORE_KX_STATE_KEY_SENT:
872 /* fine, need to send our key after updating our status, see below */ 886 /* fine, need to send our key after updating our status, see below */
873 break; 887 break;
874 case KX_STATE_KEY_RECEIVED: 888 case GNUNET_CORE_KX_STATE_KEY_RECEIVED:
875 case KX_STATE_UP: 889 case GNUNET_CORE_KX_STATE_UP:
876 case KX_STATE_REKEY_SENT: 890 case GNUNET_CORE_KX_STATE_REKEY_SENT:
877 /* other peer already got our key */ 891 /* other peer already got our key */
878 break; 892 break;
879 default: 893 default:
@@ -883,35 +897,38 @@ GSC_KX_handle_ephemeral_key (struct GSC_KeyExchangeInfo *kx,
883 /* check if we need to confirm everything is fine via PING + PONG */ 897 /* check if we need to confirm everything is fine via PING + PONG */
884 switch (kx->status) 898 switch (kx->status)
885 { 899 {
886 case KX_STATE_DOWN: 900 case GNUNET_CORE_KX_STATE_DOWN:
887 GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == kx->keep_alive_task); 901 GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == kx->keep_alive_task);
888 kx->status = KX_STATE_KEY_RECEIVED; 902 kx->status = GNUNET_CORE_KX_STATE_KEY_RECEIVED;
889 if (KX_STATE_KEY_SENT == sender_status) 903 monitor_notify_all (kx);
904 if (GNUNET_CORE_KX_STATE_KEY_SENT == sender_status)
890 send_key (kx); 905 send_key (kx);
891 send_ping (kx); 906 send_ping (kx);
892 break; 907 break;
893 case KX_STATE_KEY_SENT: 908 case GNUNET_CORE_KX_STATE_KEY_SENT:
894 GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == kx->keep_alive_task); 909 GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == kx->keep_alive_task);
895 kx->status = KX_STATE_KEY_RECEIVED; 910 kx->status = GNUNET_CORE_KX_STATE_KEY_RECEIVED;
896 if (KX_STATE_KEY_SENT == sender_status) 911 monitor_notify_all (kx);
912 if (GNUNET_CORE_KX_STATE_KEY_SENT == sender_status)
897 send_key (kx); 913 send_key (kx);
898 send_ping (kx); 914 send_ping (kx);
899 break; 915 break;
900 case KX_STATE_KEY_RECEIVED: 916 case GNUNET_CORE_KX_STATE_KEY_RECEIVED:
901 GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == kx->keep_alive_task); 917 GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == kx->keep_alive_task);
902 if (KX_STATE_KEY_SENT == sender_status) 918 if (GNUNET_CORE_KX_STATE_KEY_SENT == sender_status)
903 send_key (kx); 919 send_key (kx);
904 send_ping (kx); 920 send_ping (kx);
905 break; 921 break;
906 case KX_STATE_UP: 922 case GNUNET_CORE_KX_STATE_UP:
907 kx->status = KX_STATE_REKEY_SENT; 923 kx->status = GNUNET_CORE_KX_STATE_REKEY_SENT;
908 if (KX_STATE_KEY_SENT == sender_status) 924 monitor_notify_all (kx);
925 if (GNUNET_CORE_KX_STATE_KEY_SENT == sender_status)
909 send_key (kx); 926 send_key (kx);
910 /* we got a new key, need to reconfirm! */ 927 /* we got a new key, need to reconfirm! */
911 send_ping (kx); 928 send_ping (kx);
912 break; 929 break;
913 case KX_STATE_REKEY_SENT: 930 case GNUNET_CORE_KX_STATE_REKEY_SENT:
914 if (KX_STATE_KEY_SENT == sender_status) 931 if (GNUNET_CORE_KX_STATE_KEY_SENT == sender_status)
915 send_key (kx); 932 send_key (kx);
916 /* we got a new key, need to reconfirm! */ 933 /* we got a new key, need to reconfirm! */
917 send_ping (kx); 934 send_ping (kx);
@@ -950,9 +967,9 @@ GSC_KX_handle_ping (struct GSC_KeyExchangeInfo *kx,
950 GNUNET_STATISTICS_update (GSC_stats, 967 GNUNET_STATISTICS_update (GSC_stats,
951 gettext_noop ("# PING messages received"), 1, 968 gettext_noop ("# PING messages received"), 1,
952 GNUNET_NO); 969 GNUNET_NO);
953 if ( (kx->status != KX_STATE_KEY_RECEIVED) && 970 if ( (kx->status != GNUNET_CORE_KX_STATE_KEY_RECEIVED) &&
954 (kx->status != KX_STATE_UP) && 971 (kx->status != GNUNET_CORE_KX_STATE_UP) &&
955 (kx->status != KX_STATE_REKEY_SENT)) 972 (kx->status != GNUNET_CORE_KX_STATE_REKEY_SENT))
956 { 973 {
957 /* ignore */ 974 /* ignore */
958 GNUNET_STATISTICS_update (GSC_stats, 975 GNUNET_STATISTICS_update (GSC_stats,
@@ -1029,7 +1046,8 @@ send_keep_alive (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
1029 gettext_noop ("# sessions terminated by timeout"), 1046 gettext_noop ("# sessions terminated by timeout"),
1030 1, GNUNET_NO); 1047 1, GNUNET_NO);
1031 GSC_SESSIONS_end (&kx->peer); 1048 GSC_SESSIONS_end (&kx->peer);
1032 kx->status = KX_STATE_KEY_SENT; 1049 kx->status = GNUNET_CORE_KX_STATE_KEY_SENT;
1050 monitor_notify_all (kx);
1033 send_key (kx); 1051 send_key (kx);
1034 return; 1052 return;
1035 } 1053 }
@@ -1097,21 +1115,21 @@ GSC_KX_handle_pong (struct GSC_KeyExchangeInfo *kx,
1097 GNUNET_NO); 1115 GNUNET_NO);
1098 switch (kx->status) 1116 switch (kx->status)
1099 { 1117 {
1100 case KX_STATE_DOWN: 1118 case GNUNET_CORE_KX_STATE_DOWN:
1101 GNUNET_STATISTICS_update (GSC_stats, 1119 GNUNET_STATISTICS_update (GSC_stats,
1102 gettext_noop ("# PONG messages dropped (connection down)"), 1, 1120 gettext_noop ("# PONG messages dropped (connection down)"), 1,
1103 GNUNET_NO); 1121 GNUNET_NO);
1104 return; 1122 return;
1105 case KX_STATE_KEY_SENT: 1123 case GNUNET_CORE_KX_STATE_KEY_SENT:
1106 GNUNET_STATISTICS_update (GSC_stats, 1124 GNUNET_STATISTICS_update (GSC_stats,
1107 gettext_noop ("# PONG messages dropped (out of order)"), 1, 1125 gettext_noop ("# PONG messages dropped (out of order)"), 1,
1108 GNUNET_NO); 1126 GNUNET_NO);
1109 return; 1127 return;
1110 case KX_STATE_KEY_RECEIVED: 1128 case GNUNET_CORE_KX_STATE_KEY_RECEIVED:
1111 break; 1129 break;
1112 case KX_STATE_UP: 1130 case GNUNET_CORE_KX_STATE_UP:
1113 break; 1131 break;
1114 case KX_STATE_REKEY_SENT: 1132 case GNUNET_CORE_KX_STATE_REKEY_SENT:
1115 break; 1133 break;
1116 default: 1134 default:
1117 GNUNET_break (0); 1135 GNUNET_break (0);
@@ -1159,35 +1177,37 @@ GSC_KX_handle_pong (struct GSC_KeyExchangeInfo *kx,
1159 } 1177 }
1160 switch (kx->status) 1178 switch (kx->status)
1161 { 1179 {
1162 case KX_STATE_DOWN: 1180 case GNUNET_CORE_KX_STATE_DOWN:
1163 GNUNET_assert (0); /* should be impossible */ 1181 GNUNET_assert (0); /* should be impossible */
1164 return; 1182 return;
1165 case KX_STATE_KEY_SENT: 1183 case GNUNET_CORE_KX_STATE_KEY_SENT:
1166 GNUNET_assert (0); /* should be impossible */ 1184 GNUNET_assert (0); /* should be impossible */
1167 return; 1185 return;
1168 case KX_STATE_KEY_RECEIVED: 1186 case GNUNET_CORE_KX_STATE_KEY_RECEIVED:
1169 GNUNET_STATISTICS_update (GSC_stats, 1187 GNUNET_STATISTICS_update (GSC_stats,
1170 gettext_noop 1188 gettext_noop
1171 ("# session keys confirmed via PONG"), 1, 1189 ("# session keys confirmed via PONG"), 1,
1172 GNUNET_NO); 1190 GNUNET_NO);
1173 kx->status = KX_STATE_UP; 1191 kx->status = GNUNET_CORE_KX_STATE_UP;
1192 monitor_notify_all (kx);
1174 GSC_SESSIONS_create (&kx->peer, kx); 1193 GSC_SESSIONS_create (&kx->peer, kx);
1175 GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == kx->keep_alive_task); 1194 GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == kx->keep_alive_task);
1176 update_timeout (kx); 1195 update_timeout (kx);
1177 break; 1196 break;
1178 case KX_STATE_UP: 1197 case GNUNET_CORE_KX_STATE_UP:
1179 GNUNET_STATISTICS_update (GSC_stats, 1198 GNUNET_STATISTICS_update (GSC_stats,
1180 gettext_noop 1199 gettext_noop
1181 ("# timeouts prevented via PONG"), 1, 1200 ("# timeouts prevented via PONG"), 1,
1182 GNUNET_NO); 1201 GNUNET_NO);
1183 update_timeout (kx); 1202 update_timeout (kx);
1184 break; 1203 break;
1185 case KX_STATE_REKEY_SENT: 1204 case GNUNET_CORE_KX_STATE_REKEY_SENT:
1186 GNUNET_STATISTICS_update (GSC_stats, 1205 GNUNET_STATISTICS_update (GSC_stats,
1187 gettext_noop 1206 gettext_noop
1188 ("# rekey operations confirmed via PONG"), 1, 1207 ("# rekey operations confirmed via PONG"), 1,
1189 GNUNET_NO); 1208 GNUNET_NO);
1190 kx->status = KX_STATE_UP; 1209 kx->status = GNUNET_CORE_KX_STATE_UP;
1210 monitor_notify_all (kx);
1191 update_timeout (kx); 1211 update_timeout (kx);
1192 break; 1212 break;
1193 default: 1213 default:
@@ -1205,7 +1225,7 @@ GSC_KX_handle_pong (struct GSC_KeyExchangeInfo *kx,
1205static void 1225static void
1206send_key (struct GSC_KeyExchangeInfo *kx) 1226send_key (struct GSC_KeyExchangeInfo *kx)
1207{ 1227{
1208 GNUNET_assert (KX_STATE_DOWN != kx->status); 1228 GNUNET_assert (GNUNET_CORE_KX_STATE_DOWN != kx->status);
1209 if (GNUNET_SCHEDULER_NO_TASK != kx->retry_set_key_task) 1229 if (GNUNET_SCHEDULER_NO_TASK != kx->retry_set_key_task)
1210 { 1230 {
1211 GNUNET_SCHEDULER_cancel (kx->retry_set_key_task); 1231 GNUNET_SCHEDULER_cancel (kx->retry_set_key_task);
@@ -1321,7 +1341,7 @@ GSC_KX_handle_encrypted_message (struct GSC_KeyExchangeInfo *kx,
1321 return; 1341 return;
1322 } 1342 }
1323 m = (const struct EncryptedMessage *) msg; 1343 m = (const struct EncryptedMessage *) msg;
1324 if (KX_STATE_UP != kx->status) 1344 if (GNUNET_CORE_KX_STATE_UP != kx->status)
1325 { 1345 {
1326 GNUNET_STATISTICS_update (GSC_stats, 1346 GNUNET_STATISTICS_update (GSC_stats,
1327 gettext_noop 1347 gettext_noop
@@ -1343,7 +1363,8 @@ GSC_KX_handle_encrypted_message (struct GSC_KeyExchangeInfo *kx,
1343 GNUNET_SCHEDULER_cancel (kx->keep_alive_task); 1363 GNUNET_SCHEDULER_cancel (kx->keep_alive_task);
1344 kx->keep_alive_task = GNUNET_SCHEDULER_NO_TASK; 1364 kx->keep_alive_task = GNUNET_SCHEDULER_NO_TASK;
1345 } 1365 }
1346 kx->status = KX_STATE_KEY_SENT; 1366 kx->status = GNUNET_CORE_KX_STATE_KEY_SENT;
1367 monitor_notify_all (kx);
1347 send_key (kx); 1368 send_key (kx);
1348 return; 1369 return;
1349 } 1370 }
@@ -1473,7 +1494,7 @@ deliver_message (void *cls,
1473{ 1494{
1474 struct DeliverMessageContext *dmc = client; 1495 struct DeliverMessageContext *dmc = client;
1475 1496
1476 if (KX_STATE_UP != dmc->kx->status) 1497 if (GNUNET_CORE_KX_STATE_UP != dmc->kx->status)
1477 { 1498 {
1478 GNUNET_STATISTICS_update (GSC_stats, 1499 GNUNET_STATISTICS_update (GSC_stats,
1479 gettext_noop 1500 gettext_noop
@@ -1560,15 +1581,18 @@ do_rekey (void *cls,
1560 sign_ephemeral_key (); 1581 sign_ephemeral_key ();
1561 for (pos = kx_head; NULL != pos; pos = pos->next) 1582 for (pos = kx_head; NULL != pos; pos = pos->next)
1562 { 1583 {
1563 if (KX_STATE_UP == pos->status) 1584 if (GNUNET_CORE_KX_STATE_UP == pos->status)
1564 { 1585 {
1565 pos->status = KX_STATE_REKEY_SENT; 1586 pos->status = GNUNET_CORE_KX_STATE_REKEY_SENT;
1587 monitor_notify_all (pos);
1566 derive_session_keys (pos); 1588 derive_session_keys (pos);
1567 } 1589 }
1568 if (KX_STATE_DOWN == pos->status) 1590 if (GNUNET_CORE_KX_STATE_DOWN == pos->status)
1569 { 1591 {
1570 pos->status = KX_STATE_KEY_SENT; 1592 pos->status = GNUNET_CORE_KX_STATE_KEY_SENT;
1593 monitor_notify_all (pos);
1571 } 1594 }
1595 monitor_notify_all (pos);
1572 send_key (pos); 1596 send_key (pos);
1573 } 1597 }
1574} 1598}
@@ -1578,11 +1602,15 @@ do_rekey (void *cls,
1578 * Initialize KX subsystem. 1602 * Initialize KX subsystem.
1579 * 1603 *
1580 * @param pk private key to use for the peer 1604 * @param pk private key to use for the peer
1605 * @param server the server of the CORE service
1581 * @return #GNUNET_OK on success, #GNUNET_SYSERR on failure 1606 * @return #GNUNET_OK on success, #GNUNET_SYSERR on failure
1582 */ 1607 */
1583int 1608int
1584GSC_KX_init (struct GNUNET_CRYPTO_EddsaPrivateKey *pk) 1609GSC_KX_init (struct GNUNET_CRYPTO_EddsaPrivateKey *pk,
1610 struct GNUNET_SERVER_Handle *server)
1585{ 1611{
1612 nc = GNUNET_SERVER_notification_context_create (server,
1613 1);
1586 my_private_key = pk; 1614 my_private_key = pk;
1587 GNUNET_CRYPTO_eddsa_key_get_public (my_private_key, 1615 GNUNET_CRYPTO_eddsa_key_get_public (my_private_key,
1588 &GSC_my_identity.public_key); 1616 &GSC_my_identity.public_key);
@@ -1629,6 +1657,46 @@ GSC_KX_done ()
1629 GNUNET_SERVER_mst_destroy (mst); 1657 GNUNET_SERVER_mst_destroy (mst);
1630 mst = NULL; 1658 mst = NULL;
1631 } 1659 }
1660 if (NULL != nc)
1661 {
1662 GNUNET_SERVER_notification_context_destroy (nc);
1663 nc = NULL;
1664 }
1632} 1665}
1633 1666
1667
1668/**
1669 * Handle #GNUNET_MESSAGE_TYPE_CORE_MONITOR_PEERS request. For this
1670 * request type, the client does not have to have transmitted an INIT
1671 * request. All current peers are returned, regardless of which
1672 * message types they accept.
1673 *
1674 * @param cls unused
1675 * @param client client sending the iteration request
1676 * @param message iteration request message
1677 */
1678void
1679GSC_KX_handle_client_monitor_peers (void *cls,
1680 struct GNUNET_SERVER_Client *client,
1681 const struct GNUNET_MessageHeader *message)
1682{
1683 struct MonitorNotifyMessage done_msg;
1684 struct GSC_KeyExchangeInfo *kx;
1685
1686 GNUNET_SERVER_notification_context_add (nc,
1687 client);
1688 for (kx = kx_head; NULL != kx; kx = kx->next)
1689 monitor_notify (client, kx);
1690 done_msg.header.size = htons (sizeof (struct MonitorNotifyMessage));
1691 done_msg.header.type = htons (GNUNET_MESSAGE_TYPE_CORE_MONITOR_NOTIFY);
1692 done_msg.state = htonl ((uint32_t) GNUNET_CORE_KX_ITERATION_FINISHED);
1693 memset (&done_msg.peer, 0, sizeof (struct GNUNET_PeerIdentity));
1694 done_msg.timeout = GNUNET_TIME_absolute_hton (GNUNET_TIME_UNIT_FOREVER_ABS);
1695 GNUNET_SERVER_notification_context_unicast (nc,
1696 client,
1697 &done_msg.header,
1698 GNUNET_NO);
1699}
1700
1701
1634/* end of gnunet-service-core_kx.c */ 1702/* end of gnunet-service-core_kx.c */
diff --git a/src/core/gnunet-service-core_kx.h b/src/core/gnunet-service-core_kx.h
index c6b346ec3..abe6c3ccd 100644
--- a/src/core/gnunet-service-core_kx.h
+++ b/src/core/gnunet-service-core_kx.h
@@ -118,10 +118,12 @@ GSC_KX_stop (struct GSC_KeyExchangeInfo *kx);
118 * Initialize KX subsystem. 118 * Initialize KX subsystem.
119 * 119 *
120 * @param pk private key to use for the peer 120 * @param pk private key to use for the peer
121 * @param server the server of the CORE service
121 * @return #GNUNET_OK on success, #GNUNET_SYSERR on failure 122 * @return #GNUNET_OK on success, #GNUNET_SYSERR on failure
122 */ 123 */
123int 124int
124GSC_KX_init (struct GNUNET_CRYPTO_EddsaPrivateKey *pk); 125GSC_KX_init (struct GNUNET_CRYPTO_EddsaPrivateKey *pk,
126 struct GNUNET_SERVER_Handle *server);
125 127
126 128
127/** 129/**
@@ -130,5 +132,22 @@ GSC_KX_init (struct GNUNET_CRYPTO_EddsaPrivateKey *pk);
130void 132void
131GSC_KX_done (void); 133GSC_KX_done (void);
132 134
135
136/**
137 * Handle #GNUNET_MESSAGE_TYPE_CORE_MONITOR_PEERS request. For this
138 * request type, the client does not have to have transmitted an INIT
139 * request. All current peers are returned, regardless of which
140 * message types they accept.
141 *
142 * @param cls unused
143 * @param client client sending the iteration request
144 * @param message iteration request message
145 */
146void
147GSC_KX_handle_client_monitor_peers (void *cls,
148 struct GNUNET_SERVER_Client *client,
149 const struct GNUNET_MessageHeader *message);
150
151
133#endif 152#endif
134/* end of gnunet-service-core_kx.h */ 153/* end of gnunet-service-core_kx.h */
diff --git a/src/core/gnunet-service-core_sessions.c b/src/core/gnunet-service-core_sessions.c
index 5e8bd537f..eb0013790 100644
--- a/src/core/gnunet-service-core_sessions.c
+++ b/src/core/gnunet-service-core_sessions.c
@@ -732,59 +732,6 @@ GSC_SESSIONS_transmit (struct GSC_ClientActiveRequest *car,
732 732
733 733
734/** 734/**
735 * Helper function for #GSC_SESSIONS_handle_client_iterate_peers().
736 *
737 * @param cls the `struct GNUNET_SERVER_TransmitContext` to queue replies
738 * @param key identity of the connected peer
739 * @param value the `struct Neighbour` for the peer
740 * @return #GNUNET_OK (continue to iterate)
741 */
742static int
743queue_connect_message (void *cls,
744 const struct GNUNET_PeerIdentity *key,
745 void *value)
746{
747 struct GNUNET_SERVER_TransmitContext *tc = cls;
748 struct Session *session = value;
749 struct ConnectNotifyMessage cnm;
750
751 /* FIXME: code duplication with clients... */
752 cnm.header.size = htons (sizeof (struct ConnectNotifyMessage));
753 cnm.header.type = htons (GNUNET_MESSAGE_TYPE_CORE_NOTIFY_CONNECT);
754 cnm.reserved = htonl (0);
755 cnm.peer = session->peer;
756 GNUNET_SERVER_transmit_context_append_message (tc, &cnm.header);
757 return GNUNET_OK;
758}
759
760
761/**
762 * Handle CORE_ITERATE_PEERS request. For this request type, the client
763 * does not have to have transmitted an INIT request. All current peers
764 * are returned, regardless of which message types they accept.
765 *
766 * @param cls unused
767 * @param client client sending the iteration request
768 * @param message iteration request message
769 */
770void
771GSC_SESSIONS_handle_client_iterate_peers (void *cls,
772 struct GNUNET_SERVER_Client *client,
773 const struct GNUNET_MessageHeader *message)
774{
775 struct GNUNET_MessageHeader done_msg;
776 struct GNUNET_SERVER_TransmitContext *tc;
777
778 tc = GNUNET_SERVER_transmit_context_create (client);
779 GNUNET_CONTAINER_multipeermap_iterate (sessions, &queue_connect_message, tc);
780 done_msg.size = htons (sizeof (struct GNUNET_MessageHeader));
781 done_msg.type = htons (GNUNET_MESSAGE_TYPE_CORE_ITERATE_PEERS_END);
782 GNUNET_SERVER_transmit_context_append_message (tc, &done_msg);
783 GNUNET_SERVER_transmit_context_run (tc, GNUNET_TIME_UNIT_FOREVER_REL);
784}
785
786
787/**
788 * We've received a typemap message from a peer, update ours. 735 * We've received a typemap message from a peer, update ours.
789 * Notifies clients about the session. 736 * Notifies clients about the session.
790 * 737 *
diff --git a/src/core/gnunet-service-core_sessions.h b/src/core/gnunet-service-core_sessions.h
index 034026bb8..81581e84d 100644
--- a/src/core/gnunet-service-core_sessions.h
+++ b/src/core/gnunet-service-core_sessions.h
@@ -118,6 +118,7 @@ GSC_SESSIONS_broadcast (const struct GNUNET_MessageHeader *msg);
118void 118void
119GSC_SESSIONS_notify_client_about_sessions (struct GSC_Client *client); 119GSC_SESSIONS_notify_client_about_sessions (struct GSC_Client *client);
120 120
121
121/** 122/**
122 * We've received a typemap message from a peer, update ours. 123 * We've received a typemap message from a peer, update ours.
123 * Notifies clients about the session. 124 * Notifies clients about the session.
@@ -144,22 +145,6 @@ GSC_SESSIONS_add_to_typemap (const struct GNUNET_PeerIdentity *peer,
144 145
145 146
146/** 147/**
147 * Handle CORE_ITERATE_PEERS request. For this request type, the client
148 * does not have to have transmitted an INIT request. All current peers
149 * are returned, regardless of which message types they accept.
150 *
151 * @param cls unused
152 * @param client client sending the iteration request
153 * @param message iteration request message
154 */
155void
156GSC_SESSIONS_handle_client_iterate_peers (void *cls,
157 struct GNUNET_SERVER_Client *client,
158 const struct GNUNET_MessageHeader
159 *message);
160
161
162/**
163 * Initialize sessions subsystem. 148 * Initialize sessions subsystem.
164 */ 149 */
165void 150void