glitch in the license text detected by hyazinthe, thank you!
[oweals/gnunet.git] / src / conversation / plugin_gnsrecord_conversation.c
1 /*
2      This file is part of GNUnet
3      Copyright (C) 2013 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 conversation/plugin_gnsrecord_conversation.c
18  * @brief gnsrecord plugin to provide the API for fundamental GNS records
19  *                  This includes the VPN record because GNS resolution
20  *                  is expected to understand VPN records and (if needed)
21  *                  map the result to A/AAAA.
22  * @author Christian Grothoff
23  */
24
25 #include "platform.h"
26 #include "gnunet_util_lib.h"
27 #include "gnunet_gnsrecord_lib.h"
28 #include "gnunet_conversation_service.h"
29 #include "gnunet_gnsrecord_plugin.h"
30
31
32 /**
33  * Convert the 'value' of a record to a string.
34  *
35  * @param cls closure, unused
36  * @param type type of the record
37  * @param data value in binary encoding
38  * @param data_size number of bytes in @a data
39  * @return NULL on error, otherwise human-readable representation of the value
40  */
41 static char *
42 conversation_value_to_string (void *cls,
43                               uint32_t type,
44                               const void *data,
45                               size_t data_size)
46 {
47   char *s;
48
49   (void) cls;
50   switch (type)
51   {
52   case GNUNET_GNSRECORD_TYPE_PHONE:
53     {
54       const struct GNUNET_CONVERSATION_PhoneRecord *pr;
55       char *ret;
56       char *pkey;
57
58       if (data_size != sizeof (struct GNUNET_CONVERSATION_PhoneRecord))
59       {
60         GNUNET_break_op (0);
61         return NULL;
62       }
63       pr = data;
64       if (1 != ntohl (pr->version))
65       {
66         GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
67                     _("PHONE version %u not supported\n"),
68                     ntohl (pr->version));
69         return NULL;
70       }
71       pkey = GNUNET_CRYPTO_eddsa_public_key_to_string (&pr->peer.public_key);
72       s = GNUNET_STRINGS_data_to_string_alloc (&pr->line_port,
73                                                sizeof (struct GNUNET_HashCode));
74
75       GNUNET_asprintf (&ret,
76                        "%s-%s",
77                        s,
78                        pkey);
79       GNUNET_free (s);
80       GNUNET_free (pkey);
81       return ret;
82     }
83   default:
84     return NULL;
85   }
86 }
87
88
89 /**
90  * Convert human-readable version of a 'value' of a record to the binary
91  * representation.
92  *
93  * @param cls closure, unused
94  * @param type type of the record
95  * @param s human-readable string
96  * @param data set to value in binary encoding (will be allocated)
97  * @param data_size set to number of bytes in @a data
98  * @return #GNUNET_OK on success
99  */
100 static int
101 conversation_string_to_value (void *cls,
102                               uint32_t type,
103                               const char *s,
104                               void **data,
105                               size_t *data_size)
106 {
107   (void) cls;
108   if (NULL == s)
109   {
110     GNUNET_break (0);
111     return GNUNET_SYSERR;
112   }
113   switch (type)
114   {
115   case GNUNET_GNSRECORD_TYPE_PHONE:
116     {
117       struct GNUNET_CONVERSATION_PhoneRecord *pr;
118       char line_port[103];
119       const char *dash;
120       struct GNUNET_PeerIdentity peer;
121
122       if ( (NULL == (dash = strchr (s, '-'))) ||
123            (1 != sscanf (s, "%103s-", line_port)) ||
124            (GNUNET_OK !=
125             GNUNET_CRYPTO_eddsa_public_key_from_string (dash + 1,
126                                                         strlen (dash + 1),
127                                                         &peer.public_key)) )
128       {
129         GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
130                     _("Unable to parse PHONE record `%s'\n"),
131                     s);
132         return GNUNET_SYSERR;
133       }
134       pr = GNUNET_new (struct GNUNET_CONVERSATION_PhoneRecord);
135       pr->version = htonl (1);
136       pr->reserved = htonl (0);
137       if (GNUNET_OK !=
138           GNUNET_STRINGS_string_to_data (line_port,
139                                          strlen (line_port),
140                                          &pr->line_port,
141                                          sizeof (struct GNUNET_HashCode)))
142       {
143         GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
144                     _("Unable to parse PHONE record `%s'\n"),
145                     s);
146         GNUNET_free (pr);
147         return GNUNET_SYSERR;
148       }
149       pr->peer = peer;
150       *data = pr;
151       *data_size = sizeof (struct GNUNET_CONVERSATION_PhoneRecord);
152       return GNUNET_OK;
153     }
154   default:
155     return GNUNET_SYSERR;
156   }
157 }
158
159
160 /**
161  * Mapping of record type numbers to human-readable
162  * record type names.
163  */
164 static struct {
165   const char *name;
166   uint32_t number;
167 } name_map[] = {
168   { "PHONE",  GNUNET_GNSRECORD_TYPE_PHONE },
169   { NULL, UINT32_MAX }
170 };
171
172
173 /**
174  * Convert a type name (i.e. "AAAA") to the corresponding number.
175  *
176  * @param cls closure, unused
177  * @param gns_typename name to convert
178  * @return corresponding number, UINT32_MAX on error
179  */
180 static uint32_t
181 conversation_typename_to_number (void *cls,
182                                  const char *gns_typename)
183 {
184   unsigned int i;
185
186   (void) cls;
187   i=0;
188   while ( (name_map[i].name != NULL) &&
189           (0 != strcasecmp (gns_typename, name_map[i].name)) )
190     i++;
191   return name_map[i].number;
192 }
193
194
195 /**
196  * Convert a type number (i.e. 1) to the corresponding type string (i.e. "A")
197  *
198  * @param cls closure, unused
199  * @param type number of a type to convert
200  * @return corresponding typestring, NULL on error
201  */
202 static const char *
203 conversation_number_to_typename (void *cls,
204                                  uint32_t type)
205 {
206   unsigned int i;
207
208   (void) cls;
209   i=0;
210   while ( (name_map[i].name != NULL) &&
211           (type != name_map[i].number) )
212     i++;
213   return name_map[i].name;
214 }
215
216
217 /**
218  * Entry point for the plugin.
219  *
220  * @param cls NULL
221  * @return the exported block API
222  */
223 void *
224 libgnunet_plugin_gnsrecord_conversation_init (void *cls)
225 {
226   struct GNUNET_GNSRECORD_PluginFunctions *api;
227
228   (void) cls;
229   api = GNUNET_new (struct GNUNET_GNSRECORD_PluginFunctions);
230   api->value_to_string = &conversation_value_to_string;
231   api->string_to_value = &conversation_string_to_value;
232   api->typename_to_number = &conversation_typename_to_number;
233   api->number_to_typename = &conversation_number_to_typename;
234   return api;
235 }
236
237
238 /**
239  * Exit point from the plugin.
240  *
241  * @param cls the return value from #libgnunet_plugin_block_test_init
242  * @return NULL
243  */
244 void *
245 libgnunet_plugin_gnsrecord_conversation_done (void *cls)
246 {
247   struct GNUNET_GNSRECORD_PluginFunctions *api = cls;
248
249   GNUNET_free (api);
250   return NULL;
251 }
252
253 /* end of plugin_gnsrecord_conversation.c */