use NULL value in load_path_suffix to NOT load any files
[oweals/gnunet.git] / src / identity / identity_api_lookup.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      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 identity/identity_api_lookup.c
23  * @brief api to lookup an ego
24  * @author Christian Grothoff
25  */
26 #include "platform.h"
27 #include "gnunet_util_lib.h"
28 #include "gnunet_identity_service.h"
29 #include "identity.h"
30
31 #define LOG(kind, ...) GNUNET_log_from (kind, "identity-api", __VA_ARGS__)
32
33
34 /**
35  * Handle for ego lookup.
36  */
37 struct GNUNET_IDENTITY_EgoLookup
38 {
39   /**
40    * Connection to service.
41    */
42   struct GNUNET_MQ_Handle *mq;
43
44   /**
45    * Name of the ego we are looking up.
46    */
47   char *name;
48
49   /**
50    * Function to call with the result.
51    */
52   GNUNET_IDENTITY_EgoCallback cb;
53
54   /**
55    * Closure for @e cb
56    */
57   void *cb_cls;
58 };
59
60
61 /**
62  * We received a result code from the service.  Check the message
63  * is well-formed.
64  *
65  * @param cls closure
66  * @param rcm result message received
67  * @return #GNUNET_OK if the message is well-formed
68  */
69 static int
70 check_identity_result_code (void *cls, const struct ResultCodeMessage *rcm)
71 {
72   if (sizeof(*rcm) != htons (rcm->header.size))
73     GNUNET_MQ_check_zero_termination (rcm);
74   return GNUNET_OK;
75 }
76
77
78 /**
79  * We received a result code from the service.
80  *
81  * @param cls closure
82  * @param rcm result message received
83  */
84 static void
85 handle_identity_result_code (void *cls, const struct ResultCodeMessage *rcm)
86 {
87   struct GNUNET_IDENTITY_EgoLookup *el = cls;
88
89   el->cb (el->cb_cls, NULL);
90   GNUNET_IDENTITY_ego_lookup_cancel (el);
91 }
92
93
94 /**
95  * Check validity of identity update message.
96  *
97  * @param cls closure
98  * @param um message received
99  * @return #GNUNET_OK if the message is well-formed
100  */
101 static int
102 check_identity_update (void *cls, const struct UpdateMessage *um)
103 {
104   uint16_t size = ntohs (um->header.size);
105   uint16_t name_len = ntohs (um->name_len);
106   const char *str = (const char *) &um[1];
107
108   if ((size != name_len + sizeof(struct UpdateMessage)) ||
109       ((0 != name_len) && ('\0' != str[name_len - 1])))
110   {
111     GNUNET_break (0);
112     return GNUNET_SYSERR;
113   }
114   return GNUNET_OK;
115 }
116
117
118 /**
119  * Handle identity update message.
120  *
121  * @param cls closure
122  * @param um message received
123  */
124 static void
125 handle_identity_update (void *cls, const struct UpdateMessage *um)
126 {
127   struct GNUNET_IDENTITY_EgoLookup *el = cls;
128   uint16_t name_len = ntohs (um->name_len);
129   const char *str = (0 == name_len) ? NULL : (const char *) &um[1];
130   struct GNUNET_CRYPTO_EcdsaPublicKey pub;
131   struct GNUNET_HashCode id;
132   struct GNUNET_IDENTITY_Ego ego;
133
134   GNUNET_break (GNUNET_YES != ntohs (um->end_of_list));
135   GNUNET_CRYPTO_ecdsa_key_get_public (&um->private_key, &pub);
136   GNUNET_CRYPTO_hash (&pub, sizeof(pub), &id);
137   ego.pk = (struct GNUNET_CRYPTO_EcdsaPrivateKey *) &um->private_key;
138   ego.name = (char *) str;
139   ego.id = id;
140   el->cb (el->cb_cls, &ego);
141   GNUNET_IDENTITY_ego_lookup_cancel (el);
142 }
143
144
145 /**
146  * Generic error handler, called with the appropriate error code and
147  * the same closure specified at the creation of the message queue.
148  * Not every message queue implementation supports an error handler.
149  *
150  * @param cls closure with the `struct GNUNET_IDENTITY_EgoLookup *`
151  * @param error error code
152  */
153 static void
154 mq_error_handler (void *cls, enum GNUNET_MQ_Error error)
155 {
156   struct GNUNET_IDENTITY_EgoLookup *el = cls;
157
158   el->cb (el->cb_cls, NULL);
159 }
160
161
162 /**
163  * Lookup an ego by name.
164  *
165  * @param cfg configuration to use
166  * @param name name to look up
167  * @param cb callback to invoke with the result
168  * @param cb_cls closure for @a cb
169  * @return NULL on error
170  */
171 struct GNUNET_IDENTITY_EgoLookup *
172 GNUNET_IDENTITY_ego_lookup (const struct GNUNET_CONFIGURATION_Handle *cfg,
173                             const char *name,
174                             GNUNET_IDENTITY_EgoCallback cb,
175                             void *cb_cls)
176 {
177   struct GNUNET_IDENTITY_EgoLookup *el;
178   struct GNUNET_MQ_Envelope *env;
179   struct GNUNET_MessageHeader *req;
180   size_t nlen;
181
182   GNUNET_assert (NULL != cb);
183   el = GNUNET_new (struct GNUNET_IDENTITY_EgoLookup);
184   el->cb = cb;
185   el->cb_cls = cb_cls;
186   {
187     struct GNUNET_MQ_MessageHandler handlers[] =
188     { GNUNET_MQ_hd_var_size (identity_result_code,
189                              GNUNET_MESSAGE_TYPE_IDENTITY_RESULT_CODE,
190                              struct ResultCodeMessage,
191                              el),
192       GNUNET_MQ_hd_var_size (identity_update,
193                              GNUNET_MESSAGE_TYPE_IDENTITY_UPDATE,
194                              struct UpdateMessage,
195                              el),
196       GNUNET_MQ_handler_end () };
197
198     el->mq =
199       GNUNET_CLIENT_connect (cfg, "identity", handlers, &mq_error_handler, el);
200   }
201   if (NULL == el->mq)
202   {
203     GNUNET_break (0);
204     GNUNET_free (el);
205     return NULL;
206   }
207   el->name = GNUNET_strdup (name);
208   nlen = strlen (name) + 1;
209   env = GNUNET_MQ_msg_extra (req, nlen, GNUNET_MESSAGE_TYPE_IDENTITY_LOOKUP);
210   memcpy (&req[1], name, nlen);
211   GNUNET_MQ_send (el->mq, env);
212   return el;
213 }
214
215
216 /**
217  * Abort ego lookup attempt.
218  *
219  * @param el handle for lookup to abort
220  */
221 void
222 GNUNET_IDENTITY_ego_lookup_cancel (struct GNUNET_IDENTITY_EgoLookup *el)
223 {
224   GNUNET_MQ_destroy (el->mq);
225   GNUNET_free (el->name);
226   GNUNET_free (el);
227 }
228
229
230 /* end of identity_api_lookup.c */