src: for every AGPL3.0 file, add SPDX identifier.
[oweals/gnunet.git] / src / ats / gnunet-service-ats_connectivity.c
1 /*
2      This file is part of GNUnet.
3      Copyright (C) 2011-2015 GNUnet e.V.
4
5      GNUnet is free software: you can redistribute it and/or modify it
6      under the terms of the GNU Affero General Public License as published
7      by the Free Software Foundation, either version 3 of the License,
8      or (at your 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      Affero General Public License for more details.
14     
15      You should have received a copy of the GNU Affero General Public License
16      along with this program.  If not, see <http://www.gnu.org/licenses/>.
17
18      SPDX-License-Identifier: AGPL3.0-or-later
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_SERVICE_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   if (NULL == connection_requests)
68     return 0;
69   /* TODO: return sum of 'strength's of connectivity requests */
70   return GNUNET_CONTAINER_multipeermap_contains (connection_requests,
71                                                  peer);
72 }
73
74
75 /**
76  * Handle #GNUNET_MESSAGE_TYPE_ATS_REQUEST_ADDRESS messages from clients.
77  *
78  * @param client client that sent the request
79  * @param message the request message
80  */
81 void
82 GAS_handle_request_address (struct GNUNET_SERVICE_Client *client,
83                             const struct RequestAddressMessage *msg)
84 {
85   struct ConnectionRequest *cr;
86
87   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
88               "Received `%s' message\n",
89               "GNUNET_MESSAGE_TYPE_ATS_REQUEST_ADDRESS");
90   /* FIXME: should not ignore "msg->strength" */
91   cr = GNUNET_new (struct ConnectionRequest);
92   cr->client = client;
93   (void) GNUNET_CONTAINER_multipeermap_put (connection_requests,
94                                             &msg->peer,
95                                             cr,
96                                             GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
97   GAS_plugin_request_connect_start (&msg->peer);
98 }
99
100
101 /**
102  * Free the connection request from the map if the
103  * closure matches the client.
104  *
105  * @param cls the client to match
106  * @param pid peer for which the request was made
107  * @param value the `struct ConnectionRequest`
108  * @return #GNUNET_OK (continue to iterate)
109  */
110 static int
111 free_matching_requests (void *cls,
112                         const struct GNUNET_PeerIdentity *pid,
113                         void *value)
114 {
115   struct GNUNET_SERVICE_Client *client = cls;
116   struct ConnectionRequest *cr = value;
117
118   if (cr->client == client)
119   {
120     GAS_plugin_request_connect_stop (pid);
121     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
122                 "Removed request pending for peer `%s\n",
123                 GNUNET_i2s (pid));
124     GNUNET_assert (GNUNET_YES ==
125                    GNUNET_CONTAINER_multipeermap_remove (connection_requests,
126                                                          pid,
127                                                          cr));
128     GNUNET_free (cr);
129   }
130   return GNUNET_OK;
131 }
132
133
134 /**
135  * Handle #GNUNET_MESSAGE_TYPE_ATS_REQUEST_ADDRESS_CANCEL messages
136  * from clients.
137  *
138  * @param client the client that sent the request
139  * @param msg the request message
140  */
141 void
142 GAS_handle_request_address_cancel (struct GNUNET_SERVICE_Client *client,
143                                    const struct RequestAddressMessage *msg)
144 {
145   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
146               "Received GNUNET_MESSAGE_TYPE_ATS_REQUEST_ADDRESS_CANCEL message for peer %s\n",
147               GNUNET_i2s (&msg->peer));
148   GNUNET_break (0 == ntohl (msg->strength));
149   GNUNET_CONTAINER_multipeermap_get_multiple (connection_requests,
150                                               &msg->peer,
151                                               &free_matching_requests,
152                                               client);
153 }
154
155
156 /**
157  * Unregister a client (which may have been a connectivity client,
158  * but this is not assured).
159  *
160  * @param client handle of the (now dead) client
161  */
162 void
163 GAS_connectivity_remove_client (struct GNUNET_SERVICE_Client *client)
164 {
165   GNUNET_CONTAINER_multipeermap_iterate (connection_requests,
166                                          &free_matching_requests,
167                                          client);
168 }
169
170
171 /**
172  * Shutdown connectivity subsystem.
173  */
174 void
175 GAS_connectivity_init ()
176 {
177   connection_requests
178     = GNUNET_CONTAINER_multipeermap_create (32,
179                                             GNUNET_NO);
180 }
181
182
183 /**
184  * Free the connection request from the map.
185  *
186  * @param cls NULL
187  * @param pid peer for which the request was made
188  * @param value the `struct ConnectionRequest`
189  * @return #GNUNET_OK (continue to iterate)
190  */
191 static int
192 free_request (void *cls,
193               const struct GNUNET_PeerIdentity *pid,
194               void *value)
195 {
196   struct ConnectionRequest *cr = value;
197
198   free_matching_requests (cr->client,
199                           pid,
200                           cr);
201   return GNUNET_OK;
202 }
203
204
205 /**
206  * Shutdown connectivity subsystem.
207  */
208 void
209 GAS_connectivity_done ()
210 {
211   GAS_plugin_solver_lock ();
212   GNUNET_CONTAINER_multipeermap_iterate (connection_requests,
213                                          &free_request,
214                                          NULL);
215   GAS_plugin_solver_unlock ();
216   GNUNET_CONTAINER_multipeermap_destroy (connection_requests);
217   connection_requests = NULL;
218 }
219
220
221 /* end of gnunet-service-ats_connectivity.c */