db175964c73ed964fca4fca1a4340c1b11e86e70
[oweals/gnunet.git] / src / ats / gnunet-service-ats.c
1 /*
2      This file is part of GNUnet.
3      (C) 2009 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.c
23  * @brief ats service
24  * @author Matthias Wachs
25  */
26 #include "platform.h"
27 #include "gnunet_getopt_lib.h"
28 #include "gnunet_service_lib.h"
29 #include "gnunet_container_lib.h"
30 #include "gnunet_ats_service.h"
31 #include "ats.h"
32
33 struct ATS_Clients
34 {
35   struct ATS_Clients * next;
36
37   struct ATS_Clients * prev;
38
39   struct GNUNET_SERVER_Client *client;
40
41   uint32_t flags;
42 };
43
44 struct ATS_Address
45 {
46   struct GNUNET_PeerIdentity peer;
47
48   size_t addr_len;
49
50   uint32_t session_id;
51
52   uint32_t ats_count;
53
54   void * addr;
55
56   char * plugin;
57
58   struct GNUNET_TRANSPORT_ATS_Information * ats;
59 };
60
61 /**
62  * Head of linked list of all clients to this service.
63  */
64 static struct ATS_Clients *ac_head;
65
66 /**
67  * Tail of linked list of all clients to this service.
68  */
69 static struct ATS_Clients *ac_tail;
70
71 static struct GNUNET_CONTAINER_MultiHashMap * addresses;
72
73 int free_address_it (void *cls,
74                const GNUNET_HashCode * key,
75                void *value)
76 {
77   struct ATS_Address * aa = cls;
78   GNUNET_free (aa);
79   return GNUNET_OK;
80 }
81
82 struct CompareAddressContext
83 {
84   struct ATS_Address * search;
85   struct ATS_Address * result;
86 };
87
88 int compare_address_it (void *cls,
89                const GNUNET_HashCode * key,
90                void *value)
91 {
92   struct CompareAddressContext * cac = cls;
93   struct ATS_Address * aa = (struct ATS_Address *) value;
94   if (0 == strcmp(aa->plugin, cac->search->plugin))
95   {
96     if ((aa->addr_len == cac->search->addr_len) &&
97         (0 == memcmp (aa->addr, cac->search->addr, aa->addr_len)))
98       cac->result = aa;
99     return GNUNET_NO;
100   }
101   return GNUNET_YES;
102 }
103
104 /**
105  * Task run during shutdown.
106  *
107  * @param cls unused
108  * @param tc unused
109  */
110 static void
111 cleanup_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
112 {
113   struct ATS_Clients * t;
114
115   while (ac_head != NULL)
116   {
117     t = ac_head;
118     GNUNET_CONTAINER_DLL_remove(ac_head,ac_tail, t);
119     GNUNET_free (t);
120   }
121
122   GNUNET_CONTAINER_multihashmap_iterate (addresses, free_address_it, NULL);
123
124   GNUNET_CONTAINER_multihashmap_destroy (addresses);
125 }
126
127 static struct ATS_Clients * find_client (struct GNUNET_SERVER_Client *client)
128 {
129   struct ATS_Clients * ac = ac_head;
130   while (ac != NULL)
131   {
132   if (ac->client == client)
133     break;
134   ac = ac->next;
135   }
136   return ac;
137 }
138
139 static void
140 handle_ats_start (void *cls, struct GNUNET_SERVER_Client *client,
141                       const struct GNUNET_MessageHeader *message)
142
143 {
144   struct ClientStartMessage * msg = (struct ClientStartMessage *) message;
145   struct ATS_Clients * ac = NULL;
146
147
148   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received `%s' message\n", "ATS_START");
149
150   GNUNET_assert (find_client(client) == NULL);
151
152   ac = GNUNET_malloc (sizeof (struct ATS_Clients));
153   ac->client = client;
154   ac->flags = ntohl (msg->start_flag);
155
156   GNUNET_CONTAINER_DLL_insert(ac_head, ac_tail, ac);
157 }
158
159 static void
160 handle_request_address (void *cls, struct GNUNET_SERVER_Client *client,
161                       const struct GNUNET_MessageHeader *message)
162
163 {
164   // struct RequestAddressMessage * msg = (struct RequestAddressMessage *) message;
165   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received `%s' message\n", "REQUEST_ADDRESS");
166
167 }
168
169 static void
170 handle_address_update (void *cls, struct GNUNET_SERVER_Client *client,
171                       const struct GNUNET_MessageHeader *message)
172
173 {
174   struct AddressUpdateMessage * msg = (struct AddressUpdateMessage *) message;
175   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received `%s' message\n", "ADDRESS_UPDATE");
176
177   struct GNUNET_TRANSPORT_ATS_Information *am;
178   char *pm;
179
180   size_t size = ntohs (msg->header.size);
181   if ((size <= sizeof (struct AddressUpdateMessage)) || (size >= GNUNET_SERVER_MAX_MESSAGE_SIZE))
182   {
183     GNUNET_break (0);
184     return;
185   }
186
187   size_t ats_count = ntohs (msg->ats_count);
188   size_t addr_len = ntohs (msg->address_length);
189   size_t plugin_len = ntohs (msg->plugin_name_length) + 1 ;
190
191   if (
192        (plugin_len  >= GNUNET_SERVER_MAX_MESSAGE_SIZE) ||
193        (addr_len  >= GNUNET_SERVER_MAX_MESSAGE_SIZE) ||
194        (addr_len >= GNUNET_SERVER_MAX_MESSAGE_SIZE / sizeof (struct GNUNET_TRANSPORT_ATS_Information)) )
195   {
196     GNUNET_break (0);
197     return;
198   }
199
200   struct ATS_Address * aa = GNUNET_malloc (sizeof (struct ATS_Address) +
201                                            ats_count * sizeof (struct GNUNET_TRANSPORT_ATS_Information) +
202                                            addr_len +
203                                            plugin_len);
204
205
206
207   memcpy (&aa->peer, &msg->peer, sizeof (struct GNUNET_PeerIdentity));
208   aa->addr_len = addr_len;
209   aa->ats_count = ats_count;
210   aa->ats = (struct GNUNET_TRANSPORT_ATS_Information *) &aa[1];
211
212   am = (struct GNUNET_TRANSPORT_ATS_Information*) &msg[1];
213   memcpy (&aa->ats, am, ats_count * sizeof (struct GNUNET_TRANSPORT_ATS_Information));
214   pm = (char *) &am[ats_count];
215   memcpy (aa->addr, pm, addr_len);
216   memcpy (aa->plugin, &pm[plugin_len], plugin_len);
217   aa->session_id = ntohl(msg->session_id);
218
219   GNUNET_assert (GNUNET_OK == GNUNET_CONTAINER_multihashmap_put(addresses, &aa->peer.hashPubKey, aa, GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE));
220 }
221
222 static void
223 handle_address_destroyed (void *cls, struct GNUNET_SERVER_Client *client,
224                       const struct GNUNET_MessageHeader *message)
225
226 {
227   // struct AddressDestroyedMessage * msg = (struct AddressDestroyedMessage *) message;
228   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received `%s' message\n", "ADDRESS_DESTROYED");
229 /*
230   struct GNUNET_PeerIdentity *peer = &msg->peer;
231   struct ATS_Address * aa = find_address_by_addr (peer);
232   GNUNET_CONTAINER_multihashmap_remove(addresses, peer, aa);
233   GNUNET_free (aa);*/
234 }
235
236 static void
237 handle_reservation_request (void *cls, struct GNUNET_SERVER_Client *client,
238                       const struct GNUNET_MessageHeader *message)
239
240 {
241   // struct AddressUpdateMessage * msg = (struct AddressUpdateMessage *) message;
242   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received `%s' message\n", "RESERVATION_REQUEST");
243 }
244
245 static void
246 handle_preference_change (void *cls, struct GNUNET_SERVER_Client *client,
247                       const struct GNUNET_MessageHeader *message)
248
249 {
250   // struct ChangePreferenceMessage * msg = (struct ChangePreferenceMessage *) message;
251   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received `%s' message\n", "PREFERENCE_CHANGE");
252 }
253
254 /**
255  * Process template requests.
256  *
257  * @param cls closure
258  * @param server the initialized server
259  * @param cfg configuration to use
260  */
261 static void
262 run (void *cls, struct GNUNET_SERVER_Handle *server,
263      const struct GNUNET_CONFIGURATION_Handle *cfg)
264 {
265   static const struct GNUNET_SERVER_MessageHandler handlers[] = {
266       {&handle_ats_start, NULL, GNUNET_MESSAGE_TYPE_ATS_START, sizeof (struct ClientStartMessage)},
267       {&handle_request_address, NULL, GNUNET_MESSAGE_TYPE_ATS_REQUEST_ADDRESS, sizeof (struct RequestAddressMessage)},
268       {&handle_address_update, NULL, GNUNET_MESSAGE_TYPE_ATS_ADDRESS_UPDATE, 0},
269       {&handle_address_destroyed, NULL, GNUNET_MESSAGE_TYPE_ATS_ADDRESS_DESTROYED, 0},
270       {&handle_reservation_request, NULL, GNUNET_MESSAGE_TYPE_ATS_RESERVATION_REQUEST, sizeof (struct ReservationRequestMessage)},
271       {&handle_preference_change, NULL, GNUNET_MESSAGE_TYPE_ATS_PREFERENCE_CHANGE, 0},
272     {NULL, NULL, 0, 0}
273   };
274
275   addresses = GNUNET_CONTAINER_multihashmap_create(100);
276
277   GNUNET_SERVER_add_handlers (server, handlers);
278   GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &cleanup_task,
279                                 NULL);
280 }
281
282
283 /**
284  * The main function for the ats service.
285  *
286  * @param argc number of arguments from the command line
287  * @param argv command line arguments
288  * @return 0 ok, 1 on error
289  */
290 int
291 main (int argc, char *const *argv)
292 {
293   return (GNUNET_OK ==
294           GNUNET_SERVICE_run (argc, argv, "ats",
295                               GNUNET_SERVICE_OPTION_NONE, &run, NULL)) ? 0 : 1;
296 }
297
298 /* end of gnunet-service-ats.c */