diff options
Diffstat (limited to 'src/peerinfo/gnunet-service-peerinfo.c')
-rw-r--r-- | src/peerinfo/gnunet-service-peerinfo.c | 259 |
1 files changed, 56 insertions, 203 deletions
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 | */ | ||
94 | struct 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 | */ | ||
113 | struct 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 | */ |
142 | static struct HostEntry *hosts; | 94 | static 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 | */ |
147 | static struct NotifyList *notify_list; | 99 | static 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 | */ | ||
169 | static size_t | ||
170 | transmit_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 | */ | ||
227 | static void | ||
228 | do_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 | */ |
260 | static void | 116 | static struct InfoMessage * |
261 | notify_all (struct HostEntry *he) | 117 | make_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 | */ | ||
216 | static void | ||
217 | notify_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 | */ |
873 | static void | 757 | static void |
874 | notify_disconnect (void *cls, | 758 | shutdown_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, ¬ify_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 | ||