glitch in the license text detected by hyazinthe, thank you!
[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
16 /**
17  * @file ats/gnunet-service-ats_connectivity.c
18  * @brief ats service, interaction with 'connecivity' API
19  * @author Matthias Wachs
20  * @author Christian Grothoff
21  */
22 #include "platform.h"
23 #include "gnunet-service-ats.h"
24 #include "gnunet-service-ats_addresses.h"
25 #include "gnunet-service-ats_connectivity.h"
26 #include "gnunet-service-ats_plugins.h"
27 #include "ats.h"
28
29
30 /**
31  * Active connection requests.
32  */
33 struct ConnectionRequest
34 {
35   /**
36    * Client that made the request.
37    */
38   struct GNUNET_SERVICE_Client *client;
39
40   /* TODO: allow client to express a 'strength' for this request */
41 };
42
43
44 /**
45  * Address suggestion requests by peer.
46  */
47 static struct GNUNET_CONTAINER_MultiPeerMap *connection_requests;
48
49
50 /**
51  * Is the given peer in the list of peers for which we
52  * have an address request?
53  *
54  * @param cls unused, NULL
55  * @param peer peer to query for
56  * @return #GNUNET_YES if so, #GNUNET_NO if not
57  */
58 unsigned int
59 GAS_connectivity_has_peer (void *cls,
60                            const struct GNUNET_PeerIdentity *peer)
61 {
62   if (NULL == connection_requests)
63     return 0;
64   /* TODO: return sum of 'strength's of connectivity requests */
65   return GNUNET_CONTAINER_multipeermap_contains (connection_requests,
66                                                  peer);
67 }
68
69
70 /**
71  * Handle #GNUNET_MESSAGE_TYPE_ATS_REQUEST_ADDRESS messages from clients.
72  *
73  * @param client client that sent the request
74  * @param message the request message
75  */
76 void
77 GAS_handle_request_address (struct GNUNET_SERVICE_Client *client,
78                             const struct RequestAddressMessage *msg)
79 {
80   struct ConnectionRequest *cr;
81
82   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
83               "Received `%s' message\n",
84               "GNUNET_MESSAGE_TYPE_ATS_REQUEST_ADDRESS");
85   /* FIXME: should not ignore "msg->strength" */
86   cr = GNUNET_new (struct ConnectionRequest);
87   cr->client = client;
88   (void) GNUNET_CONTAINER_multipeermap_put (connection_requests,
89                                             &msg->peer,
90                                             cr,
91                                             GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
92   GAS_plugin_request_connect_start (&msg->peer);
93 }
94
95
96 /**
97  * Free the connection request from the map if the
98  * closure matches the client.
99  *
100  * @param cls the client to match
101  * @param pid peer for which the request was made
102  * @param value the `struct ConnectionRequest`
103  * @return #GNUNET_OK (continue to iterate)
104  */
105 static int
106 free_matching_requests (void *cls,
107                         const struct GNUNET_PeerIdentity *pid,
108                         void *value)
109 {
110   struct GNUNET_SERVICE_Client *client = cls;
111   struct ConnectionRequest *cr = value;
112
113   if (cr->client == client)
114   {
115     GAS_plugin_request_connect_stop (pid);
116     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
117                 "Removed request pending for peer `%s\n",
118                 GNUNET_i2s (pid));
119     GNUNET_assert (GNUNET_YES ==
120                    GNUNET_CONTAINER_multipeermap_remove (connection_requests,
121                                                          pid,
122                                                          cr));
123     GNUNET_free (cr);
124   }
125   return GNUNET_OK;
126 }
127
128
129 /**
130  * Handle #GNUNET_MESSAGE_TYPE_ATS_REQUEST_ADDRESS_CANCEL messages
131  * from clients.
132  *
133  * @param client the client that sent the request
134  * @param msg the request message
135  */
136 void
137 GAS_handle_request_address_cancel (struct GNUNET_SERVICE_Client *client,
138                                    const struct RequestAddressMessage *msg)
139 {
140   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
141               "Received GNUNET_MESSAGE_TYPE_ATS_REQUEST_ADDRESS_CANCEL message for peer %s\n",
142               GNUNET_i2s (&msg->peer));
143   GNUNET_break (0 == ntohl (msg->strength));
144   GNUNET_CONTAINER_multipeermap_get_multiple (connection_requests,
145                                               &msg->peer,
146                                               &free_matching_requests,
147                                               client);
148 }
149
150
151 /**
152  * Unregister a client (which may have been a connectivity client,
153  * but this is not assured).
154  *
155  * @param client handle of the (now dead) client
156  */
157 void
158 GAS_connectivity_remove_client (struct GNUNET_SERVICE_Client *client)
159 {
160   GNUNET_CONTAINER_multipeermap_iterate (connection_requests,
161                                          &free_matching_requests,
162                                          client);
163 }
164
165
166 /**
167  * Shutdown connectivity subsystem.
168  */
169 void
170 GAS_connectivity_init ()
171 {
172   connection_requests
173     = GNUNET_CONTAINER_multipeermap_create (32,
174                                             GNUNET_NO);
175 }
176
177
178 /**
179  * Free the connection request from the map.
180  *
181  * @param cls NULL
182  * @param pid peer for which the request was made
183  * @param value the `struct ConnectionRequest`
184  * @return #GNUNET_OK (continue to iterate)
185  */
186 static int
187 free_request (void *cls,
188               const struct GNUNET_PeerIdentity *pid,
189               void *value)
190 {
191   struct ConnectionRequest *cr = value;
192
193   free_matching_requests (cr->client,
194                           pid,
195                           cr);
196   return GNUNET_OK;
197 }
198
199
200 /**
201  * Shutdown connectivity subsystem.
202  */
203 void
204 GAS_connectivity_done ()
205 {
206   GAS_plugin_solver_lock ();
207   GNUNET_CONTAINER_multipeermap_iterate (connection_requests,
208                                          &free_request,
209                                          NULL);
210   GAS_plugin_solver_unlock ();
211   GNUNET_CONTAINER_multipeermap_destroy (connection_requests);
212   connection_requests = NULL;
213 }
214
215
216 /* end of gnunet-service-ats_connectivity.c */