aboutsummaryrefslogtreecommitdiff
path: root/src/transport/gnunet-service-transport_clients.c
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2012-02-06 09:35:56 +0000
committerChristian Grothoff <christian@grothoff.org>2012-02-06 09:35:56 +0000
commit7e599b44d257d9d9c6100e4050dc1eb09c9e13d2 (patch)
tree6f63e09cf3a296d4daf6135077b58a9006e564e9 /src/transport/gnunet-service-transport_clients.c
parentdc0da555fd351b2a96bca0a6494e83f0643fac31 (diff)
downloadgnunet-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.c253
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 */
122struct 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 */
122static struct TransportClient *clients_head; 151static struct TransportClient *clients_head;
@@ -127,6 +156,23 @@ static struct TransportClient *clients_head;
127static struct TransportClient *clients_tail; 156static struct TransportClient *clients_tail;
128 157
129/** 158/**
159 * Head of linked list of monitoring clients.
160 */
161static struct MonitoringClient *monitoring_clients_head;
162
163/**
164 * Tail of linked list of monitoring clients.
165 */
166static struct MonitoringClient *monitoring_clients_tail;
167
168/**
169 * Notification context, to send updates on changes to active addresses
170 * of our neighbours.
171 */
172struct 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 */
226static struct MonitoringClient *
227lookup_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 */
251static struct MonitoringClient *
252setup_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
287client_disconnect_notification (void *cls, struct GNUNET_SERVER_Client *client) 387client_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 */
808static struct AddressIterateResponseMessage *
809compose_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)
837void 979void
838GST_clients_stop () 980GST_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 */
1036void
1037GST_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 */