-fin, mention future work in TODO
[oweals/gnunet.git] / src / ats / gnunet-service-ats_connectivity.c
1 /*
2      This file is part of GNUnet.
3      Copyright (C) 2011-2015 Christian Grothoff (and other contributing authors)
4
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
7      by the Free Software Foundation; either version 3, or (at your
8      option) any later version.
9
10      GNUnet is distributed in the hope that it will be useful, but
11      WITHOUT ANY WARRANTY; without even the implied warranty of
12      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13      General Public License for more details.
14
15      You should have received a copy of the GNU General Public License
16      along with GNUnet; see the file COPYING.  If not, write to the
17      Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18      Boston, MA 02111-1307, USA.
19 */
20
21 /**
22  * @file ats/gnunet-service-ats_connectivity.c
23  * @brief ats service, interaction with 'connecivity' API
24  * @author Matthias Wachs
25  * @author Christian Grothoff
26  */
27 #include "platform.h"
28 #include "gnunet-service-ats.h"
29 #include "gnunet-service-ats_addresses.h"
30 #include "gnunet-service-ats_connectivity.h"
31 #include "gnunet-service-ats_plugins.h"
32 #include "ats.h"
33
34
35 /**
36  * Active connection requests.
37  */
38 struct ConnectionRequest
39 {
40   /**
41    * Client that made the request.
42    */
43   struct GNUNET_SERVER_Client *client;
44
45   /* TODO: allow client to express a 'strength' for this request */
46 };
47
48
49 /**
50  * Address suggestion requests by peer.
51  */
52 static struct GNUNET_CONTAINER_MultiPeerMap *connection_requests;
53
54
55 /**
56  * Is the given peer in the list of peers for which we
57  * have an address request?
58  *
59  * @param cls unused, NULL
60  * @param peer peer to query for
61  * @return #GNUNET_YES if so, #GNUNET_NO if not
62  */
63 unsigned int
64 GAS_connectivity_has_peer (void *cls,
65                            const struct GNUNET_PeerIdentity *peer)
66 {
67   /* TODO: return sum of 'strength's of connectivity requests */
68   return GNUNET_CONTAINER_multipeermap_contains (connection_requests,
69                                                  peer);
70 }
71
72
73 /**
74  * Handle 'request address' messages from clients.
75  *
76  * @param cls unused, NULL
77  * @param client client that sent the request
78  * @param message the request message
79  */
80 void
81 GAS_handle_request_address (void *cls,
82                             struct GNUNET_SERVER_Client *client,
83                             const struct GNUNET_MessageHeader *message)
84 {
85   const struct RequestAddressMessage *msg =
86       (const struct RequestAddressMessage *) message;
87   struct ConnectionRequest *cr;
88
89   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
90               "Received `%s' message\n",
91               "REQUEST_ADDRESS");
92   GNUNET_break (0 == ntohl (msg->reserved));
93   cr = GNUNET_new (struct ConnectionRequest);
94   cr->client = client;
95   (void) GNUNET_CONTAINER_multipeermap_put (connection_requests,
96                                             &msg->peer,
97                                             cr,
98                                             GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
99   GAS_plugin_request_connect_start (&msg->peer);
100   GNUNET_SERVER_receive_done (client, GNUNET_OK);
101 }
102
103
104 /**
105  * Free the connection request from the map if the
106  * closure matches the client.
107  *
108  * @param cls the client to match
109  * @param pid peer for which the request was made
110  * @param value the `struct ConnectionRequest`
111  * @return #GNUNET_OK (continue to iterate)
112  */
113 static int
114 free_matching_requests (void *cls,
115                         const struct GNUNET_PeerIdentity *pid,
116                         void *value)
117 {
118   struct GNUNET_SERVER_Client *client = cls;
119   struct ConnectionRequest *cr = value;
120
121   if (cr->client == client)
122   {
123     GAS_plugin_request_connect_stop (pid);
124     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
125                 "Removed request pending for peer `%s\n",
126                 GNUNET_i2s (pid));
127     GNUNET_assert (GNUNET_YES ==
128                    GNUNET_CONTAINER_multipeermap_remove (connection_requests,
129                                                          pid,
130                                                          cr));
131     GNUNET_free (cr);
132   }
133   return GNUNET_OK;
134 }
135
136
137 /**
138  * Handle 'request address cancel' messages from clients.
139  *
140  * @param cls unused, NULL
141  * @param client client that sent the request
142  * @param message the request message
143  */
144 void
145 GAS_handle_request_address_cancel (void *cls,
146                                    struct GNUNET_SERVER_Client *client,
147                                    const struct GNUNET_MessageHeader *message)
148 {
149   const struct RequestAddressMessage *msg =
150       (const struct RequestAddressMessage *) message;
151
152   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
153               "Received REQUEST_ADDRESS_CANCEL message for peer %s\n",
154               GNUNET_i2s (&msg->peer));
155   GNUNET_break (0 == ntohl (msg->reserved));
156   GNUNET_CONTAINER_multipeermap_get_multiple (connection_requests,
157                                               &msg->peer,
158                                               &free_matching_requests,
159                                               client);
160   GNUNET_SERVER_receive_done (client, GNUNET_OK);
161 }
162
163
164 /**
165  * Unregister a client (which may have been a connectivity client,
166  * but this is not assured).
167  *
168  * @param client handle of the (now dead) client
169  */
170 void
171 GAS_connectivity_remove_client (struct GNUNET_SERVER_Client *client)
172 {
173   GNUNET_CONTAINER_multipeermap_iterate (connection_requests,
174                                          &free_matching_requests,
175                                          client);
176 }
177
178
179 /**
180  * Shutdown connectivity subsystem.
181  */
182 void
183 GAS_connectivity_init ()
184 {
185   connection_requests = GNUNET_CONTAINER_multipeermap_create (32, GNUNET_NO);
186 }
187
188
189 /**
190  * Free the connection request from the map.
191  *
192  * @param cls NULL
193  * @param pid peer for which the request was made
194  * @param value the `struct ConnectionRequest`
195  * @return #GNUNET_OK (continue to iterate)
196  */
197 static int
198 free_request (void *cls,
199               const struct GNUNET_PeerIdentity *pid,
200               void *value)
201 {
202   struct ConnectionRequest *cr = value;
203
204   free_matching_requests (cr->client,
205                           pid,
206                           cr);
207   return GNUNET_OK;
208 }
209
210
211 /**
212  * Shutdown connectivity subsystem.
213  */
214 void
215 GAS_connectivity_done ()
216 {
217   GNUNET_CONTAINER_multipeermap_iterate (connection_requests,
218                                          &free_request,
219                                          NULL);
220   GNUNET_CONTAINER_multipeermap_destroy (connection_requests);
221 }
222
223
224 /* end of gnunet-service-ats_connectivity.c */