aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--TODO7
-rw-r--r--src/core/gnunet-service-core.c2
-rw-r--r--src/datastore/gnunet-service-datastore.c2
-rw-r--r--src/fs/gnunet-service-fs.c2
-rw-r--r--src/include/gnunet_server_lib.h9
-rw-r--r--src/peerinfo/gnunet-service-peerinfo.c259
-rw-r--r--src/transport/gnunet-service-transport.c2
-rw-r--r--src/transport/plugin_transport_tcp.c2
-rw-r--r--src/util/server.c1
-rw-r--r--src/util/server_nc.c12
-rw-r--r--src/util/test_server_disconnect.c2
-rw-r--r--src/util/test_server_with_client.c2
12 files changed, 91 insertions, 211 deletions
diff --git a/TODO b/TODO
index 992f61f80..cfeec44d1 100644
--- a/TODO
+++ b/TODO
@@ -18,8 +18,8 @@ Urgent items (before announcing ng.gnunet.org):
18 of having each service queue messages and "send when ready", 18 of having each service queue messages and "send when ready",
19 simply have a way to add a client to the notification set 19 simply have a way to add a client to the notification set
20 and to 'notify client' or 'notify all clients' 20 and to 'notify client' or 'notify all clients'
21 (useful for peerinfo (new hellos), transport (our hello; blacklist), 21 (transport (our hello),
22 core (misc monitoring features), statistics (change notifications) 22 core (misc monitoring features)
23 and likely others) 23 and likely others)
24 - server/service API change for ARM inetd'ing 24 - server/service API change for ARM inetd'ing
25 (listen as well as support for start with multiple, already 25 (listen as well as support for start with multiple, already
@@ -66,7 +66,8 @@ Urgent items (before announcing ng.gnunet.org):
66 (async peerinfo would not be right) 66 (async peerinfo would not be right)
67 - OS: existing waitpid call is not nice (not integratable with scheduler! fix this!) 67 - OS: existing waitpid call is not nice (not integratable with scheduler! fix this!)
68* STATISTICS: 68* STATISTICS:
69 - synchronous/asynchronous API (& implementation) is not nice 69 - synchronous/asynchronous API (& implementation) is not nice;
70 => provide notification-based API
70 - does not seem to work with timeouts (especially if service is not running) 71 - does not seem to work with timeouts (especially if service is not running)
71* ARM: 72* ARM:
72 - need to get rid of synchronous API for service starts (cause all kinds of problems) 73 - need to get rid of synchronous API for service starts (cause all kinds of problems)
diff --git a/src/core/gnunet-service-core.c b/src/core/gnunet-service-core.c
index 32b39fd7f..915217ea1 100644
--- a/src/core/gnunet-service-core.c
+++ b/src/core/gnunet-service-core.c
@@ -1034,6 +1034,8 @@ handle_client_disconnect (void *cls, struct GNUNET_SERVER_Client *client)
1034 struct Client *prev; 1034 struct Client *prev;
1035 struct Event *e; 1035 struct Event *e;
1036 1036
1037 if (client == NULL)
1038 return;
1037#if DEBUG_CORE_CLIENT 1039#if DEBUG_CORE_CLIENT
1038 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1040 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1039 "Client has disconnected from core service.\n"); 1041 "Client has disconnected from core service.\n");
diff --git a/src/datastore/gnunet-service-datastore.c b/src/datastore/gnunet-service-datastore.c
index 1766ef96c..161fbc1d8 100644
--- a/src/datastore/gnunet-service-datastore.c
+++ b/src/datastore/gnunet-service-datastore.c
@@ -1233,6 +1233,8 @@ cleanup_reservations (void *cls,
1233 struct ReservationList *prev; 1233 struct ReservationList *prev;
1234 struct ReservationList *next; 1234 struct ReservationList *next;
1235 1235
1236 if (client == NULL)
1237 return;
1236 prev = NULL; 1238 prev = NULL;
1237 pos = reservations; 1239 pos = reservations;
1238 while (NULL != pos) 1240 while (NULL != pos)
diff --git a/src/fs/gnunet-service-fs.c b/src/fs/gnunet-service-fs.c
index 541f656c6..b8855632c 100644
--- a/src/fs/gnunet-service-fs.c
+++ b/src/fs/gnunet-service-fs.c
@@ -2273,6 +2273,8 @@ handle_client_disconnect (void *cls,
2273 struct ClientList *cprev; 2273 struct ClientList *cprev;
2274 struct ClientRequestList *rl; 2274 struct ClientRequestList *rl;
2275 2275
2276 if (client == NULL)
2277 return;
2276 lgc = lgc_head; 2278 lgc = lgc_head;
2277 while ( (NULL != lgc) && 2279 while ( (NULL != lgc) &&
2278 (lgc->client != client) ) 2280 (lgc->client != client) )
diff --git a/src/include/gnunet_server_lib.h b/src/include/gnunet_server_lib.h
index 100dc9659..5609d7a9e 100644
--- a/src/include/gnunet_server_lib.h
+++ b/src/include/gnunet_server_lib.h
@@ -394,7 +394,8 @@ int GNUNET_SERVER_client_get_address (struct GNUNET_SERVER_Client *client,
394 * is disconnected on the network level. 394 * is disconnected on the network level.
395 * 395 *
396 * @param cls closure 396 * @param cls closure
397 * @param client identification of the client 397 * @param client identification of the client; NULL
398 * for the last call when the server is destroyed
398 */ 399 */
399typedef void (*GNUNET_SERVER_DisconnectCallback) (void *cls, 400typedef void (*GNUNET_SERVER_DisconnectCallback) (void *cls,
400 struct GNUNET_SERVER_Client 401 struct GNUNET_SERVER_Client
@@ -405,7 +406,11 @@ typedef void (*GNUNET_SERVER_DisconnectCallback) (void *cls,
405 * Ask the server to notify us whenever a client disconnects. 406 * Ask the server to notify us whenever a client disconnects.
406 * This function is called whenever the actual network connection 407 * This function is called whenever the actual network connection
407 * is closed; the reference count may be zero or larger than zero 408 * is closed; the reference count may be zero or larger than zero
408 * at this point. 409 * at this point. If the server is destroyed before this
410 * notification is explicitly cancelled, the 'callback' will
411 * once be called with a 'client' argument of NULL to indicate
412 * that the server itself is now gone (and that the callback
413 * won't be called anymore and also can no longer be cancelled).
409 * 414 *
410 * @param server the server manageing the clients 415 * @param server the server manageing the clients
411 * @param callback function to call on disconnect 416 * @param callback function to call on disconnect
diff --git a/src/peerinfo/gnunet-service-peerinfo.c b/src/peerinfo/gnunet-service-peerinfo.c
index 2f3e2c8e1..5b2b999d6 100644
--- a/src/peerinfo/gnunet-service-peerinfo.c
+++ b/src/peerinfo/gnunet-service-peerinfo.c
@@ -89,54 +89,6 @@ struct HostEntry
89 89
90 90
91/** 91/**
92 * Entries that we still need to tell the client about.
93 */
94struct PendingEntry
95{
96
97 /**
98 * This is a linked list.
99 */
100 struct PendingEntry *next;
101
102 /**
103 * Entry to tell the client about.
104 */
105 struct HostEntry *he;
106
107};
108
109
110/**
111 * Clients to notify of changes to the peer information.
112 */
113struct NotifyList
114{
115
116 /**
117 * This is a linked list.
118 */
119 struct NotifyList *next;
120
121 /**
122 * Client to notify.
123 */
124 struct GNUNET_SERVER_Client *client;
125
126 /**
127 * Notifications pending for this entry.
128 */
129 struct PendingEntry *pending;
130
131 /**
132 * Handle for a transmit ready request.
133 */
134 struct GNUNET_CONNECTION_TransmitHandle *transmit_ctx;
135
136};
137
138
139/**
140 * The in-memory list of known hosts. 92 * The in-memory list of known hosts.
141 */ 93 */
142static struct HostEntry *hosts; 94static struct HostEntry *hosts;
@@ -144,7 +96,7 @@ static struct HostEntry *hosts;
144/** 96/**
145 * Clients to immediately notify about all changes. 97 * Clients to immediately notify about all changes.
146 */ 98 */
147static struct NotifyList *notify_list; 99static struct GNUNET_SERVER_NotificationContext *notify_list;
148 100
149/** 101/**
150 * Directory where the hellos are stored in (data/hosts) 102 * Directory where the hellos are stored in (data/hosts)
@@ -158,116 +110,23 @@ static char *trustDirectory;
158 110
159 111
160/** 112/**
161 * Transmit peer information messages from the pending queue
162 * to the client.
163 *
164 * @param cls the 'struct NotifyList' that we are processing
165 * @param size number of bytes we can transmit
166 * @param vbuf where to write the messages
167 * @return number of bytes written to vbuf
168 */
169static size_t
170transmit_pending_notification (void *cls,
171 size_t size,
172 void *vbuf)
173{
174 struct NotifyList *nl = cls;
175 char *buf = vbuf;
176 struct PendingEntry *pos;
177 struct PendingEntry *next;
178 struct InfoMessage im;
179 uint16_t hs;
180 size_t left;
181
182 nl->transmit_ctx = NULL;
183 next = nl->pending;
184 pos = nl->pending;
185 left = size;
186 while (pos != NULL)
187 {
188 hs = (pos->he->hello == NULL) ? 0 : GNUNET_HELLO_size (pos->he->hello);
189 if (left < sizeof (struct InfoMessage) + hs)
190 break;
191 next = pos->next;
192 im.header.size = htons (hs + sizeof (struct InfoMessage));
193 im.header.type = htons (GNUNET_MESSAGE_TYPE_PEERINFO_INFO);
194 im.trust = htonl (pos->he->trust);
195 im.peer = pos->he->identity;
196 memcpy (&buf[size - left], &im, sizeof (struct InfoMessage));
197 memcpy (&buf[size - left + sizeof (struct InfoMessage)], pos->he->hello, hs);
198 left -= hs + sizeof (struct InfoMessage);
199 GNUNET_free (pos);
200 pos = next;
201 }
202 nl->pending = next;
203 if (nl->pending != NULL)
204 {
205 nl->transmit_ctx
206 = GNUNET_SERVER_notify_transmit_ready (nl->client,
207 sizeof (struct InfoMessage) + hs,
208 GNUNET_TIME_UNIT_FOREVER_REL,
209 &transmit_pending_notification,
210 nl);
211 }
212 return size - left;
213}
214
215
216
217/**
218 * Notify client about host change. Checks if the
219 * respective host entry is already in the list of things
220 * to send to the client, and if not, adds it. Also
221 * triggers a new request for transmission if the pending
222 * list was previously empty.
223 *
224 * @param nl client to notify
225 * @param he entry to notify about
226 */
227static void
228do_notify (struct NotifyList *nl,
229 struct HostEntry *he)
230{
231 struct PendingEntry *pe;
232 uint16_t hsize;
233
234 pe = nl->pending;
235 while (NULL != pe)
236 {
237 if (pe->he == he)
238 return; /* already in list */
239 pe = pe->next;
240 }
241 pe = GNUNET_malloc (sizeof (struct PendingEntry));
242 pe->next = nl->pending;
243 pe->he = he;
244 nl->pending = pe;
245 if (nl->transmit_ctx != NULL)
246 return; /* already trying to transmit */
247 hsize = (he->hello == NULL) ? 0 : GNUNET_HELLO_size (he->hello);
248 nl->transmit_ctx = GNUNET_SERVER_notify_transmit_ready (nl->client,
249 sizeof (struct InfoMessage) + hsize,
250 GNUNET_TIME_UNIT_FOREVER_REL,
251 &transmit_pending_notification,
252 nl);
253}
254
255
256/**
257 * Notify all clients in the notify list about the 113 * Notify all clients in the notify list about the
258 * given host entry changing. 114 * given host entry changing.
259 */ 115 */
260static void 116static struct InfoMessage *
261notify_all (struct HostEntry *he) 117make_info_message (const struct HostEntry *he)
262{ 118{
263 struct NotifyList *nl; 119 struct InfoMessage *im;
264 120 size_t hs;
265 nl = notify_list; 121
266 while (NULL != nl) 122 hs = (he->hello == NULL) ? 0 : GNUNET_HELLO_size (he->hello);
267 { 123 im = GNUNET_malloc (sizeof (struct InfoMessage) + hs);
268 do_notify (nl, he); 124 im->header.size = htons (hs + sizeof (struct InfoMessage));
269 nl = nl->next; 125 im->header.type = htons (GNUNET_MESSAGE_TYPE_PEERINFO_INFO);
270 } 126 im->trust = htonl (he->trust);
127 im->peer = he->identity;
128 memcpy (&im[1], he->hello, hs);
129 return im;
271} 130}
272 131
273 132
@@ -328,6 +187,7 @@ get_trust_filename (const struct GNUNET_PeerIdentity *id)
328 return fn; 187 return fn;
329} 188}
330 189
190
331/** 191/**
332 * Find the host entry for the given peer. Call 192 * Find the host entry for the given peer. Call
333 * only when synchronized! 193 * only when synchronized!
@@ -348,6 +208,25 @@ lookup_host_entry (const struct GNUNET_PeerIdentity *id)
348 208
349 209
350/** 210/**
211 * Broadcast information about the given entry to all
212 * clients that care.
213 *
214 * @param entry entry to broadcast about
215 */
216static void
217notify_all (struct HostEntry *entry)
218{
219 struct InfoMessage *msg;
220
221 msg = make_info_message (entry);
222 GNUNET_SERVER_notification_context_broadcast (notify_list,
223 &msg->header,
224 GNUNET_NO);
225 GNUNET_free (msg);
226}
227
228
229/**
351 * Add a host to the list. 230 * Add a host to the list.
352 * 231 *
353 * @param identity the identity of the host 232 * @param identity the identity of the host
@@ -451,7 +330,7 @@ change_host_trust (const struct GNUNET_PeerIdentity *hostId, int value)
451 host->trust += value; 330 host->trust += value;
452 } 331 }
453 if (host->trust != old_trust) 332 if (host->trust != old_trust)
454 notify_all (host); 333 notify_all (host);
455 return value; 334 return value;
456} 335}
457 336
@@ -834,18 +713,20 @@ handle_notify (void *cls,
834 struct GNUNET_SERVER_Client *client, 713 struct GNUNET_SERVER_Client *client,
835 const struct GNUNET_MessageHeader *message) 714 const struct GNUNET_MessageHeader *message)
836{ 715{
837 struct NotifyList *nl; 716 struct InfoMessage *msg;
838 struct HostEntry *pos; 717 struct HostEntry *pos;
839 718
840 nl = GNUNET_malloc (sizeof (struct NotifyList)); 719 GNUNET_SERVER_notification_context_add (notify_list,
841 nl->next = notify_list; 720 client);
842 nl->client = client;
843 GNUNET_SERVER_client_keep (client);
844 notify_list = nl;
845 pos = hosts; 721 pos = hosts;
846 while (NULL != pos) 722 while (NULL != pos)
847 { 723 {
848 do_notify (nl, pos); 724 msg = make_info_message (pos);
725 GNUNET_SERVER_notification_context_unicast (notify_list,
726 client,
727 &msg->header,
728 GNUNET_NO);
729 GNUNET_free (msg);
849 pos = pos->next; 730 pos = pos->next;
850 } 731 }
851} 732}
@@ -868,48 +749,17 @@ static struct GNUNET_SERVER_MessageHandler handlers[] = {
868 749
869 750
870/** 751/**
871 * Function that is called when a client disconnects. 752 * Clean up our state. Called during shutdown.
753 *
754 * @param cls unused
755 * @param tc scheduler task context, unused
872 */ 756 */
873static void 757static void
874notify_disconnect (void *cls, 758shutdown_task (void *cls,
875 struct GNUNET_SERVER_Client *client) 759 const struct GNUNET_SCHEDULER_TaskContext *tc)
876{ 760{
877 struct NotifyList *pos; 761 GNUNET_SERVER_notification_context_destroy (notify_list);
878 struct NotifyList *prev; 762 notify_list = NULL;
879 struct NotifyList *next;
880 struct PendingEntry *p;
881
882 pos = notify_list;
883 prev = NULL;
884 while (pos != NULL)
885 {
886 next = pos->next;
887 if (pos->client == client)
888 {
889 while (NULL != (p = pos->pending))
890 {
891 pos->pending = p->next;
892 GNUNET_free (p);
893 }
894 if (pos->transmit_ctx != NULL)
895 {
896 GNUNET_CONNECTION_notify_transmit_ready_cancel (pos->transmit_ctx);
897 pos->transmit_ctx = NULL;
898 }
899 if (prev == NULL)
900 notify_list = next;
901 else
902 prev->next = next;
903 GNUNET_SERVER_client_drop (client);
904 GNUNET_free (pos);
905 }
906 else
907 {
908 prev = pos;
909 }
910 pos = next;
911 }
912
913} 763}
914 764
915 765
@@ -927,6 +777,7 @@ run (void *cls,
927 struct GNUNET_SERVER_Handle *server, 777 struct GNUNET_SERVER_Handle *server,
928 const struct GNUNET_CONFIGURATION_Handle *cfg) 778 const struct GNUNET_CONFIGURATION_Handle *cfg)
929{ 779{
780 notify_list = GNUNET_SERVER_notification_context_create (server, 0);
930 GNUNET_assert (GNUNET_OK == 781 GNUNET_assert (GNUNET_OK ==
931 GNUNET_CONFIGURATION_get_value_filename (cfg, 782 GNUNET_CONFIGURATION_get_value_filename (cfg,
932 "peerinfo", 783 "peerinfo",
@@ -948,7 +799,9 @@ run (void *cls,
948 GNUNET_SCHEDULER_add_with_priority (sched, 799 GNUNET_SCHEDULER_add_with_priority (sched,
949 GNUNET_SCHEDULER_PRIORITY_IDLE, 800 GNUNET_SCHEDULER_PRIORITY_IDLE,
950 &cron_clean_data_hosts, NULL); 801 &cron_clean_data_hosts, NULL);
951 GNUNET_SERVER_disconnect_notify (server, &notify_disconnect, NULL); 802 GNUNET_SCHEDULER_add_delayed (sched,
803 GNUNET_TIME_UNIT_FOREVER_REL,
804 &shutdown_task, NULL);
952 GNUNET_SERVER_add_handlers (server, handlers); 805 GNUNET_SERVER_add_handlers (server, handlers);
953} 806}
954 807
diff --git a/src/transport/gnunet-service-transport.c b/src/transport/gnunet-service-transport.c
index b05e8360a..fe8b5043e 100644
--- a/src/transport/gnunet-service-transport.c
+++ b/src/transport/gnunet-service-transport.c
@@ -2743,6 +2743,8 @@ client_disconnect_notification (void *cls,
2743 struct TransportClient *prev; 2743 struct TransportClient *prev;
2744 struct ClientMessageQueueEntry *mqe; 2744 struct ClientMessageQueueEntry *mqe;
2745 2745
2746 if (client == NULL)
2747 return;
2746#if DEBUG_TRANSPORT 2748#if DEBUG_TRANSPORT
2747 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK, 2749 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK,
2748 "Client disconnected, cleaning up.\n"); 2750 "Client disconnected, cleaning up.\n");
diff --git a/src/transport/plugin_transport_tcp.c b/src/transport/plugin_transport_tcp.c
index 23ed867b7..51b1ce5e1 100644
--- a/src/transport/plugin_transport_tcp.c
+++ b/src/transport/plugin_transport_tcp.c
@@ -1146,6 +1146,8 @@ disconnect_notify (void *cls, struct GNUNET_SERVER_Client *client)
1146 struct Plugin *plugin = cls; 1146 struct Plugin *plugin = cls;
1147 struct Session *session; 1147 struct Session *session;
1148 1148
1149 if (client == NULL)
1150 return;
1149 session = find_session_by_client (plugin, client); 1151 session = find_session_by_client (plugin, client);
1150 if (session == NULL) 1152 if (session == NULL)
1151 return; /* unknown, nothing to do */ 1153 return; /* unknown, nothing to do */
diff --git a/src/util/server.c b/src/util/server.c
index adc19ecb7..6f2ffe232 100644
--- a/src/util/server.c
+++ b/src/util/server.c
@@ -538,6 +538,7 @@ GNUNET_SERVER_destroy (struct GNUNET_SERVER_Handle *s)
538 } 538 }
539 while (NULL != (npos = s->disconnect_notify_list)) 539 while (NULL != (npos = s->disconnect_notify_list))
540 { 540 {
541 npos->callback (npos->callback_cls, NULL);
541 s->disconnect_notify_list = npos->next; 542 s->disconnect_notify_list = npos->next;
542 GNUNET_free (npos); 543 GNUNET_free (npos);
543 } 544 }
diff --git a/src/util/server_nc.c b/src/util/server_nc.c
index 9b6eefe1f..05a4913a8 100644
--- a/src/util/server_nc.c
+++ b/src/util/server_nc.c
@@ -146,6 +146,11 @@ handle_client_disconnect (void *cls,
146 struct ClientList *prev; 146 struct ClientList *prev;
147 struct PendingMessageList *pml; 147 struct PendingMessageList *pml;
148 148
149 if (client == NULL)
150 {
151 nc->server = NULL;
152 return;
153 }
149 prev = NULL; 154 prev = NULL;
150 pos = nc->clients; 155 pos = nc->clients;
151 while (NULL != pos) 156 while (NULL != pos)
@@ -219,9 +224,10 @@ GNUNET_SERVER_notification_context_destroy (struct GNUNET_SERVER_NotificationCon
219 } 224 }
220 GNUNET_free (pos); 225 GNUNET_free (pos);
221 } 226 }
222 GNUNET_SERVER_disconnect_notify_cancel (nc->server, 227 if (nc->server != NULL)
223 &handle_client_disconnect, 228 GNUNET_SERVER_disconnect_notify_cancel (nc->server,
224 nc); 229 &handle_client_disconnect,
230 nc);
225 GNUNET_free (nc); 231 GNUNET_free (nc);
226} 232}
227 233
diff --git a/src/util/test_server_disconnect.c b/src/util/test_server_disconnect.c
index 76a73d348..b10719e73 100644
--- a/src/util/test_server_disconnect.c
+++ b/src/util/test_server_disconnect.c
@@ -138,6 +138,8 @@ disconnect_notify (void *cls, const struct GNUNET_MessageHeader *msg)
138static void 138static void
139notify_disconnect (void *cls, struct GNUNET_SERVER_Client *clientarg) 139notify_disconnect (void *cls, struct GNUNET_SERVER_Client *clientarg)
140{ 140{
141 if (clientarg == NULL)
142 return;
141 GNUNET_assert (ok == 6); 143 GNUNET_assert (ok == 6);
142 ok++; 144 ok++;
143 GNUNET_CLIENT_receive (client, 145 GNUNET_CLIENT_receive (client,
diff --git a/src/util/test_server_with_client.c b/src/util/test_server_with_client.c
index 68b842ef8..adce0b432 100644
--- a/src/util/test_server_with_client.c
+++ b/src/util/test_server_with_client.c
@@ -123,6 +123,8 @@ clean_up (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
123static void 123static void
124notify_disconnect (void *cls, struct GNUNET_SERVER_Client *client) 124notify_disconnect (void *cls, struct GNUNET_SERVER_Client *client)
125{ 125{
126 if (client == NULL)
127 return;
126 GNUNET_assert (ok == 5); 128 GNUNET_assert (ok == 5);
127 ok = 0; 129 ok = 0;
128 GNUNET_SCHEDULER_add_now (sched, 130 GNUNET_SCHEDULER_add_now (sched,