-bringing copyright tags up to FSF standard
[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
46
47 /**
48  * Address suggestion requests by peer.
49  */
50 static struct GNUNET_CONTAINER_MultiPeerMap *connection_requests;
51
52
53 /**
54  * Is the given peer in the list of peers for which we
55  * have an address request?
56  *
57  * @param peer peer to query for
58  * @return #GNUNET_YES if so, #GNUNET_NO if not
59  */
60 int
61 GAS_connectivity_has_peer (const struct GNUNET_PeerIdentity *peer)
62 {
63   return GNUNET_CONTAINER_multipeermap_contains (connection_requests,
64                                                  peer);
65 }
66
67
68 /**
69  * Handle 'request address' messages from clients.
70  *
71  * @param cls unused, NULL
72  * @param client client that sent the request
73  * @param message the request message
74  */
75 void
76 GAS_handle_request_address (void *cls,
77                             struct GNUNET_SERVER_Client *client,
78                             const struct GNUNET_MessageHeader *message)
79 {
80   const struct RequestAddressMessage *msg =
81       (const struct RequestAddressMessage *) message;
82   struct ConnectionRequest *cr;
83
84   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
85               "Received `%s' message\n",
86               "REQUEST_ADDRESS");
87   GNUNET_break (0 == ntohl (msg->reserved));
88   cr = GNUNET_new (struct ConnectionRequest);
89   cr->client = client;
90   (void) GNUNET_CONTAINER_multipeermap_put (connection_requests,
91                                             &msg->peer,
92                                             cr,
93                                             GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
94   GAS_plugin_request_connect_start (&msg->peer);
95   GNUNET_SERVER_receive_done (client, GNUNET_OK);
96 }
97
98
99 /**
100  * Free the connection request from the map if the
101  * closure matches the client.
102  *
103  * @param cls the client to match
104  * @param pid peer for which the request was made
105  * @param value the `struct ConnectionRequest`
106  * @return #GNUNET_OK (continue to iterate)
107  */
108 static int
109 free_matching_requests (void *cls,
110                         const struct GNUNET_PeerIdentity *pid,
111                         void *value)
112 {
113   struct GNUNET_SERVER_Client *client = cls;
114   struct ConnectionRequest *cr = value;
115
116   if (cr->client == client)
117   {
118     GAS_plugin_request_connect_stop (pid);
119     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
120                 "Removed request pending for peer `%s\n",
121                 GNUNET_i2s (pid));
122     GNUNET_assert (GNUNET_YES ==
123                    GNUNET_CONTAINER_multipeermap_remove (connection_requests,
124                                                          pid,
125                                                          cr));
126     GNUNET_free (cr);
127   }
128   return GNUNET_OK;
129 }
130
131
132 /**
133  * Handle 'request address cancel' messages from clients.
134  *
135  * @param cls unused, NULL
136  * @param client client that sent the request
137  * @param message the request message
138  */
139 void
140 GAS_handle_request_address_cancel (void *cls,
141                                    struct GNUNET_SERVER_Client *client,
142                                    const struct GNUNET_MessageHeader *message)
143 {
144   const struct RequestAddressMessage *msg =
145       (const struct RequestAddressMessage *) message;
146
147   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
148               "Received REQUEST_ADDRESS_CANCEL message for peer %s\n",
149               GNUNET_i2s (&msg->peer));
150   GNUNET_break (0 == ntohl (msg->reserved));
151   GNUNET_CONTAINER_multipeermap_get_multiple (connection_requests,
152                                               &msg->peer,
153                                               &free_matching_requests,
154                                               client);
155   GNUNET_SERVER_receive_done (client, GNUNET_OK);
156 }
157
158
159 /**
160  * Unregister a client (which may have been a connectivity client,
161  * but this is not assured).
162  *
163  * @param client handle of the (now dead) client
164  */
165 void
166 GAS_connectivity_remove_client (struct GNUNET_SERVER_Client *client)
167 {
168   GNUNET_CONTAINER_multipeermap_iterate (connection_requests,
169                                          &free_matching_requests,
170                                          client);
171 }
172
173
174 /**
175  * Shutdown connectivity subsystem.
176  */
177 void
178 GAS_connectivity_init ()
179 {
180   connection_requests = GNUNET_CONTAINER_multipeermap_create (32, GNUNET_NO);
181 }
182
183
184 /**
185  * Free the connection request from the map.
186  *
187  * @param cls NULL
188  * @param pid peer for which the request was made
189  * @param value the `struct ConnectionRequest`
190  * @return #GNUNET_OK (continue to iterate)
191  */
192 static int
193 free_request (void *cls,
194               const struct GNUNET_PeerIdentity *pid,
195               void *value)
196 {
197   struct ConnectionRequest *cr = value;
198
199   free_matching_requests (cr->client,
200                           pid,
201                           cr);
202   return GNUNET_OK;
203 }
204
205
206 /**
207  * Shutdown connectivity subsystem.
208  */
209 void
210 GAS_connectivity_done ()
211 {
212   GNUNET_CONTAINER_multipeermap_iterate (connection_requests,
213                                          &free_request,
214                                          NULL);
215   GNUNET_CONTAINER_multipeermap_destroy (connection_requests);
216 }
217
218
219 /* end of gnunet-service-ats_connectivity.c */