diff options
author | Christian Grothoff <christian@grothoff.org> | 2012-02-06 09:35:56 +0000 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2012-02-06 09:35:56 +0000 |
commit | 7e599b44d257d9d9c6100e4050dc1eb09c9e13d2 (patch) | |
tree | 6f63e09cf3a296d4daf6135077b58a9006e564e9 /src/transport/gnunet-service-transport_clients.c | |
parent | dc0da555fd351b2a96bca0a6494e83f0643fac31 (diff) | |
download | gnunet-7e599b44d257d9d9c6100e4050dc1eb09c9e13d2.tar.gz gnunet-7e599b44d257d9d9c6100e4050dc1eb09c9e13d2.zip |
-applying patch from vminko to fix #1972: adding support for continuous transport-level connection monitoring
Diffstat (limited to 'src/transport/gnunet-service-transport_clients.c')
-rw-r--r-- | src/transport/gnunet-service-transport_clients.c | 253 |
1 files changed, 217 insertions, 36 deletions
diff --git a/src/transport/gnunet-service-transport_clients.c b/src/transport/gnunet-service-transport_clients.c index 7ce455f7d..3cc5aac34 100644 --- a/src/transport/gnunet-service-transport_clients.c +++ b/src/transport/gnunet-service-transport_clients.c | |||
@@ -117,6 +117,35 @@ struct TransportClient | |||
117 | 117 | ||
118 | 118 | ||
119 | /** | 119 | /** |
120 | * Client monitoring changes of active addresses of our neighbours. | ||
121 | */ | ||
122 | struct MonitoringClient | ||
123 | { | ||
124 | /** | ||
125 | * This is a doubly-linked list. | ||
126 | */ | ||
127 | struct MonitoringClient *next; | ||
128 | |||
129 | /** | ||
130 | * This is a doubly-linked list. | ||
131 | */ | ||
132 | struct MonitoringClient *prev; | ||
133 | |||
134 | /** | ||
135 | * Handle to the client. | ||
136 | */ | ||
137 | struct GNUNET_SERVER_Client *client; | ||
138 | |||
139 | /** | ||
140 | * Peer identity to monitor the addresses of. | ||
141 | * Zero to monitor all neighrours. | ||
142 | */ | ||
143 | struct GNUNET_PeerIdentity peer; | ||
144 | |||
145 | }; | ||
146 | |||
147 | |||
148 | /** | ||
120 | * Head of linked list of all clients to this service. | 149 | * Head of linked list of all clients to this service. |
121 | */ | 150 | */ |
122 | static struct TransportClient *clients_head; | 151 | static struct TransportClient *clients_head; |
@@ -127,6 +156,23 @@ static struct TransportClient *clients_head; | |||
127 | static struct TransportClient *clients_tail; | 156 | static struct TransportClient *clients_tail; |
128 | 157 | ||
129 | /** | 158 | /** |
159 | * Head of linked list of monitoring clients. | ||
160 | */ | ||
161 | static struct MonitoringClient *monitoring_clients_head; | ||
162 | |||
163 | /** | ||
164 | * Tail of linked list of monitoring clients. | ||
165 | */ | ||
166 | static struct MonitoringClient *monitoring_clients_tail; | ||
167 | |||
168 | /** | ||
169 | * Notification context, to send updates on changes to active addresses | ||
170 | * of our neighbours. | ||
171 | */ | ||
172 | struct GNUNET_SERVER_NotificationContext *nc = NULL; | ||
173 | |||
174 | |||
175 | /** | ||
130 | * Find the internal handle associated with the given client handle | 176 | * Find the internal handle associated with the given client handle |
131 | * | 177 | * |
132 | * @param client server's client handle to look up | 178 | * @param client server's client handle to look up |
@@ -171,6 +217,60 @@ setup_client (struct GNUNET_SERVER_Client *client) | |||
171 | 217 | ||
172 | 218 | ||
173 | /** | 219 | /** |
220 | * Find the handle to the monitoring client associated with the given | ||
221 | * client handle | ||
222 | * | ||
223 | * @param client server's client handle to look up | ||
224 | * @return handle to the monitoring client | ||
225 | */ | ||
226 | static struct MonitoringClient * | ||
227 | lookup_monitoring_client (struct GNUNET_SERVER_Client *client) | ||
228 | { | ||
229 | struct MonitoringClient *mc; | ||
230 | |||
231 | mc = monitoring_clients_head; | ||
232 | while (mc != NULL) | ||
233 | { | ||
234 | if (mc->client == client) | ||
235 | return mc; | ||
236 | mc = mc->next; | ||
237 | } | ||
238 | return NULL; | ||
239 | } | ||
240 | |||
241 | |||
242 | /** | ||
243 | * Setup a new monitoring client using the given server client handle and | ||
244 | * the peer identity. | ||
245 | * | ||
246 | * @param client server's client handle to create our internal handle for | ||
247 | * @param peer identity of the peer to monitor the addresses of, | ||
248 | * zero to monitor all neighrours. | ||
249 | * @return handle to the new monitoring client | ||
250 | */ | ||
251 | static struct MonitoringClient * | ||
252 | setup_monitoring_client (struct GNUNET_SERVER_Client *client, | ||
253 | struct GNUNET_PeerIdentity *peer) | ||
254 | { | ||
255 | struct MonitoringClient *mc; | ||
256 | |||
257 | GNUNET_assert (lookup_monitoring_client (client) == NULL); | ||
258 | mc = GNUNET_malloc (sizeof (struct MonitoringClient)); | ||
259 | mc->client = client; | ||
260 | mc->peer = *peer; | ||
261 | GNUNET_CONTAINER_DLL_insert (monitoring_clients_head, | ||
262 | monitoring_clients_tail, | ||
263 | mc); | ||
264 | GNUNET_SERVER_notification_context_add (nc, client); | ||
265 | |||
266 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
267 | "Client %X started monitoring of the peer `%s'\n", | ||
268 | mc, GNUNET_i2s (peer)); | ||
269 | return mc; | ||
270 | } | ||
271 | |||
272 | |||
273 | /** | ||
174 | * Function called to notify a client about the socket being ready to | 274 | * Function called to notify a client about the socket being ready to |
175 | * queue more data. "buf" will be NULL and "size" zero if the socket | 275 | * queue more data. "buf" will be NULL and "size" zero if the socket |
176 | * was closed for writing in the meantime. | 276 | * was closed for writing in the meantime. |
@@ -287,10 +387,19 @@ static void | |||
287 | client_disconnect_notification (void *cls, struct GNUNET_SERVER_Client *client) | 387 | client_disconnect_notification (void *cls, struct GNUNET_SERVER_Client *client) |
288 | { | 388 | { |
289 | struct TransportClient *tc; | 389 | struct TransportClient *tc; |
390 | struct MonitoringClient *mc; | ||
290 | struct ClientMessageQueueEntry *mqe; | 391 | struct ClientMessageQueueEntry *mqe; |
291 | 392 | ||
292 | if (client == NULL) | 393 | if (client == NULL) |
293 | return; | 394 | return; |
395 | mc = lookup_monitoring_client (client); | ||
396 | if (mc != NULL) | ||
397 | { | ||
398 | GNUNET_CONTAINER_DLL_remove (monitoring_clients_head, | ||
399 | monitoring_clients_tail, | ||
400 | mc); | ||
401 | GNUNET_free (mc); | ||
402 | } | ||
294 | tc = lookup_client (client); | 403 | tc = lookup_client (client); |
295 | if (tc == NULL) | 404 | if (tc == NULL) |
296 | return; | 405 | return; |
@@ -690,6 +799,52 @@ clients_handle_address_to_string (void *cls, | |||
690 | 799 | ||
691 | 800 | ||
692 | /** | 801 | /** |
802 | * Compose AddressIterateResponseMessage using the given peer and address. | ||
803 | * | ||
804 | * @param peer identity of the peer | ||
805 | * @param address the address, NULL on disconnect | ||
806 | * @return composed message | ||
807 | */ | ||
808 | static struct AddressIterateResponseMessage * | ||
809 | compose_address_iterate_response_message (const struct GNUNET_PeerIdentity | ||
810 | *peer, | ||
811 | const struct GNUNET_HELLO_Address | ||
812 | *address) | ||
813 | { | ||
814 | struct AddressIterateResponseMessage *msg; | ||
815 | size_t size; | ||
816 | size_t tlen; | ||
817 | size_t alen; | ||
818 | char *addr; | ||
819 | |||
820 | GNUNET_assert (NULL != peer); | ||
821 | if (NULL != address) | ||
822 | { | ||
823 | tlen = strlen (address->transport_name) + 1; | ||
824 | alen = address->address_length; | ||
825 | } | ||
826 | else | ||
827 | tlen = alen = 0; | ||
828 | size = (sizeof (struct AddressIterateResponseMessage) + alen + tlen); | ||
829 | msg = GNUNET_malloc (size); | ||
830 | msg->header.size = htons (size); | ||
831 | msg->header.type = | ||
832 | htons (GNUNET_MESSAGE_TYPE_TRANSPORT_ADDRESS_ITERATE_RESPONSE); | ||
833 | msg->reserved = htonl (0); | ||
834 | msg->peer = *peer; | ||
835 | msg->addrlen = htonl (alen); | ||
836 | msg->pluginlen = htonl (tlen); | ||
837 | if (NULL != address) | ||
838 | { | ||
839 | addr = (char *) &msg[1]; | ||
840 | memcpy (addr, address->address, alen); | ||
841 | memcpy (&addr[alen], address->transport_name, tlen); | ||
842 | } | ||
843 | return msg; | ||
844 | } | ||
845 | |||
846 | |||
847 | /** | ||
693 | * Output the active address of connected neighbours to the given client. | 848 | * Output the active address of connected neighbours to the given client. |
694 | * | 849 | * |
695 | * @param cls the 'struct GNUNET_SERVER_TransmitContext' for transmission to the client | 850 | * @param cls the 'struct GNUNET_SERVER_TransmitContext' for transmission to the client |
@@ -705,34 +860,10 @@ output_address (void *cls, const struct GNUNET_PeerIdentity *peer, | |||
705 | { | 860 | { |
706 | struct GNUNET_SERVER_TransmitContext *tc = cls; | 861 | struct GNUNET_SERVER_TransmitContext *tc = cls; |
707 | struct AddressIterateResponseMessage *msg; | 862 | struct AddressIterateResponseMessage *msg; |
708 | size_t size; | ||
709 | size_t tlen; | ||
710 | size_t alen; | ||
711 | char *addr; | ||
712 | 863 | ||
713 | tlen = strlen (address->transport_name) + 1; | 864 | msg = compose_address_iterate_response_message (peer, address); |
714 | alen = address->address_length; | 865 | GNUNET_SERVER_transmit_context_append_message (tc, &msg->header); |
715 | size = (sizeof (struct AddressIterateResponseMessage) + alen + tlen); | 866 | GNUNET_free (msg); |
716 | { | ||
717 | char buf[size]; | ||
718 | |||
719 | msg = (struct AddressIterateResponseMessage *) buf; | ||
720 | msg->reserved = htonl (0); | ||
721 | msg->peer = *peer; | ||
722 | msg->addrlen = htonl (alen); | ||
723 | msg->pluginlen = htonl (tlen); | ||
724 | addr = (char *) &msg[1]; | ||
725 | memcpy (addr, address->address, alen); | ||
726 | memcpy (&addr[alen], address->transport_name, tlen); | ||
727 | GNUNET_SERVER_transmit_context_append_data (tc, | ||
728 | &buf[sizeof | ||
729 | (struct | ||
730 | GNUNET_MessageHeader)], | ||
731 | size - | ||
732 | sizeof (struct | ||
733 | GNUNET_MessageHeader), | ||
734 | GNUNET_MESSAGE_TYPE_TRANSPORT_ADDRESS_ITERATE_RESPONSE); | ||
735 | } | ||
736 | } | 867 | } |
737 | 868 | ||
738 | 869 | ||
@@ -753,6 +884,7 @@ clients_handle_address_iterate (void *cls, struct GNUNET_SERVER_Client *client, | |||
753 | struct GNUNET_SERVER_TransmitContext *tc; | 884 | struct GNUNET_SERVER_TransmitContext *tc; |
754 | struct AddressIterateMessage *msg; | 885 | struct AddressIterateMessage *msg; |
755 | struct GNUNET_HELLO_Address *address; | 886 | struct GNUNET_HELLO_Address *address; |
887 | struct MonitoringClient *mc; | ||
756 | 888 | ||
757 | if (ntohs (message->type) != GNUNET_MESSAGE_TYPE_TRANSPORT_ADDRESS_ITERATE) | 889 | if (ntohs (message->type) != GNUNET_MESSAGE_TYPE_TRANSPORT_ADDRESS_ITERATE) |
758 | { | 890 | { |
@@ -767,13 +899,6 @@ clients_handle_address_iterate (void *cls, struct GNUNET_SERVER_Client *client, | |||
767 | return; | 899 | return; |
768 | } | 900 | } |
769 | msg = (struct AddressIterateMessage *) message; | 901 | msg = (struct AddressIterateMessage *) message; |
770 | if (GNUNET_YES != ntohl (msg->one_shot)) | ||
771 | { | ||
772 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
773 | "Address monitoring not implemented\n"); | ||
774 | GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); | ||
775 | return; | ||
776 | } | ||
777 | GNUNET_SERVER_disable_receive_done_warning (client); | 902 | GNUNET_SERVER_disable_receive_done_warning (client); |
778 | tc = GNUNET_SERVER_transmit_context_create (client); | 903 | tc = GNUNET_SERVER_transmit_context_create (client); |
779 | if (0 == memcmp (&msg->peer, &all_zeros, sizeof (struct GNUNET_PeerIdentity))) | 904 | if (0 == memcmp (&msg->peer, &all_zeros, sizeof (struct GNUNET_PeerIdentity))) |
@@ -788,8 +913,24 @@ clients_handle_address_iterate (void *cls, struct GNUNET_SERVER_Client *client, | |||
788 | if (address != NULL) | 913 | if (address != NULL) |
789 | output_address (tc, &msg->peer, NULL, 0, address); | 914 | output_address (tc, &msg->peer, NULL, 0, address); |
790 | } | 915 | } |
916 | if (GNUNET_YES != ntohl (msg->one_shot)) | ||
917 | { | ||
918 | mc = lookup_monitoring_client (client); | ||
919 | if (mc != NULL) | ||
920 | { | ||
921 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK, | ||
922 | "ServerClient %X tried to start monitoring twice (MonitoringClient %X)\n", | ||
923 | client, mc); | ||
924 | GNUNET_break (0); | ||
925 | GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); | ||
926 | return; | ||
927 | } | ||
928 | setup_monitoring_client (client, &msg->peer); | ||
929 | GNUNET_SERVER_receive_done (client, GNUNET_OK); | ||
930 | return; | ||
931 | } | ||
791 | GNUNET_SERVER_transmit_context_append_data (tc, NULL, 0, | 932 | GNUNET_SERVER_transmit_context_append_data (tc, NULL, 0, |
792 | GNUNET_MESSAGE_TYPE_TRANSPORT_ADDRESS_ITERATE_RESPONSE); | 933 | GNUNET_MESSAGE_TYPE_TRANSPORT_ADDRESS_ITERATE_RESPONSE); |
793 | GNUNET_SERVER_transmit_context_run (tc, GNUNET_TIME_UNIT_FOREVER_REL); | 934 | GNUNET_SERVER_transmit_context_run (tc, GNUNET_TIME_UNIT_FOREVER_REL); |
794 | } | 935 | } |
795 | 936 | ||
@@ -825,6 +966,7 @@ GST_clients_start (struct GNUNET_SERVER_Handle *server) | |||
825 | sizeof (struct BlacklistMessage)}, | 966 | sizeof (struct BlacklistMessage)}, |
826 | {NULL, NULL, 0, 0} | 967 | {NULL, NULL, 0, 0} |
827 | }; | 968 | }; |
969 | nc = GNUNET_SERVER_notification_context_create (server, 0); | ||
828 | GNUNET_SERVER_add_handlers (server, handlers); | 970 | GNUNET_SERVER_add_handlers (server, handlers); |
829 | GNUNET_SERVER_disconnect_notify (server, &client_disconnect_notification, | 971 | GNUNET_SERVER_disconnect_notify (server, &client_disconnect_notification, |
830 | NULL); | 972 | NULL); |
@@ -837,7 +979,11 @@ GST_clients_start (struct GNUNET_SERVER_Handle *server) | |||
837 | void | 979 | void |
838 | GST_clients_stop () | 980 | GST_clients_stop () |
839 | { | 981 | { |
840 | /* nothing to do */ | 982 | if (NULL != nc) |
983 | { | ||
984 | GNUNET_SERVER_notification_context_destroy (nc); | ||
985 | nc = NULL; | ||
986 | } | ||
841 | } | 987 | } |
842 | 988 | ||
843 | 989 | ||
@@ -881,4 +1027,39 @@ GST_clients_unicast (struct GNUNET_SERVER_Client *client, | |||
881 | } | 1027 | } |
882 | 1028 | ||
883 | 1029 | ||
1030 | /** | ||
1031 | * Broadcast the new active address to all clients monitoring the peer. | ||
1032 | * | ||
1033 | * @param peer peer this update is about (never NULL) | ||
1034 | * @param address address, NULL on disconnect | ||
1035 | */ | ||
1036 | void | ||
1037 | GST_clients_broadcast_address_notification (const struct GNUNET_PeerIdentity | ||
1038 | *peer, | ||
1039 | const struct GNUNET_HELLO_Address | ||
1040 | *address) | ||
1041 | { | ||
1042 | struct AddressIterateResponseMessage *msg; | ||
1043 | struct MonitoringClient *mc; | ||
1044 | static struct GNUNET_PeerIdentity all_zeros; | ||
1045 | |||
1046 | msg = compose_address_iterate_response_message (peer, address); | ||
1047 | mc = monitoring_clients_head; | ||
1048 | while (mc != NULL) | ||
1049 | { | ||
1050 | if ((0 == memcmp (&mc->peer, &all_zeros, | ||
1051 | sizeof (struct GNUNET_PeerIdentity))) || | ||
1052 | (0 == memcmp (&mc->peer, peer, | ||
1053 | sizeof (struct GNUNET_PeerIdentity)))) | ||
1054 | { | ||
1055 | GNUNET_SERVER_notification_context_unicast (nc, mc->client, | ||
1056 | &msg->header, GNUNET_NO); | ||
1057 | } | ||
1058 | |||
1059 | mc = mc->next; | ||
1060 | } | ||
1061 | GNUNET_free (msg); | ||
1062 | } | ||
1063 | |||
1064 | |||
884 | /* end of file gnunet-service-transport_clients.c */ | 1065 | /* end of file gnunet-service-transport_clients.c */ |