error handling
[oweals/gnunet.git] / src / identity / identity_api_suffix_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_suffix_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_EgoSuffixLookup
38 {
39   /**
40    * Connection to service.
41    */
42   struct GNUNET_MQ_Handle *mq;
43
44   /**
45    * Suffix we are looking up.
46    */
47   char *suffix;
48
49   /**
50    * Function to call with the result.
51    */
52   GNUNET_IDENTITY_EgoSuffixCallback 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   (void) cls;
73   if (sizeof(*rcm) != htons (rcm->header.size))
74     GNUNET_MQ_check_zero_termination (rcm);
75   return GNUNET_OK;
76 }
77
78
79 /**
80  * We received a result code from the service.
81  *
82  * @param cls closure
83  * @param rcm result message received
84  */
85 static void
86 handle_identity_result_code (void *cls, const struct ResultCodeMessage *rcm)
87 {
88   struct GNUNET_IDENTITY_EgoSuffixLookup *el = cls;
89
90   (void) rcm;
91   el->cb (el->cb_cls, NULL, NULL);
92   GNUNET_IDENTITY_ego_lookup_by_suffix_cancel (el);
93 }
94
95
96 /**
97  * Check validity of identity update message.
98  *
99  * @param cls closure
100  * @param um message received
101  * @return #GNUNET_OK if the message is well-formed
102  */
103 static int
104 check_identity_update (void *cls, const struct UpdateMessage *um)
105 {
106   uint16_t size = ntohs (um->header.size);
107   uint16_t name_len = ntohs (um->name_len);
108   const char *str = (const char *) &um[1];
109
110   (void) cls;
111   if ((size != name_len + sizeof(struct UpdateMessage)) ||
112       ((0 != name_len) && ('\0' != str[name_len - 1])))
113   {
114     GNUNET_break (0);
115     return GNUNET_SYSERR;
116   }
117   return GNUNET_OK;
118 }
119
120
121 /**
122  * Handle identity update message.
123  *
124  * @param cls closure
125  * @param um message received
126  */
127 static void
128 handle_identity_update (void *cls, const struct UpdateMessage *um)
129 {
130   struct GNUNET_IDENTITY_EgoSuffixLookup *el = cls;
131   uint16_t name_len = ntohs (um->name_len);
132   const char *str = (0 == name_len) ? NULL : (const char *) &um[1];
133
134   el->cb (el->cb_cls, &um->private_key, str);
135   GNUNET_IDENTITY_ego_lookup_by_suffix_cancel (el);
136 }
137
138
139 /**
140  * Generic error handler, called with the appropriate error code and
141  * the same closure specified at the creation of the message queue.
142  * Not every message queue implementation supports an error handler.
143  *
144  * @param cls closure with the `struct GNUNET_IDENTITY_EgoSuffixLookup *`
145  * @param error error code
146  */
147 static void
148 mq_error_handler (void *cls, enum GNUNET_MQ_Error error)
149 {
150   struct GNUNET_IDENTITY_EgoSuffixLookup *el = cls;
151
152   (void) error;
153   el->cb (el->cb_cls, NULL, NULL);
154   GNUNET_IDENTITY_ego_lookup_by_suffix_cancel (el);
155 }
156
157
158 /**
159  * Lookup an ego by name.
160  *
161  * @param cfg configuration to use
162  * @param name name to look up
163  * @param cb callback to invoke with the result
164  * @param cb_cls closure for @a cb
165  * @return NULL on error
166  */
167 struct GNUNET_IDENTITY_EgoSuffixLookup *
168 GNUNET_IDENTITY_ego_lookup_by_suffix (const struct
169                                       GNUNET_CONFIGURATION_Handle *cfg,
170                                       const char *suffix,
171                                       GNUNET_IDENTITY_EgoSuffixCallback cb,
172                                       void *cb_cls)
173 {
174   struct GNUNET_IDENTITY_EgoSuffixLookup *el;
175   struct GNUNET_MQ_Envelope *env;
176   struct GNUNET_MessageHeader *req;
177   size_t nlen;
178
179   GNUNET_assert (NULL != cb);
180   el = GNUNET_new (struct GNUNET_IDENTITY_EgoSuffixLookup);
181   el->cb = cb;
182   el->cb_cls = cb_cls;
183   {
184     struct GNUNET_MQ_MessageHandler handlers[] =
185     { GNUNET_MQ_hd_var_size (identity_result_code,
186                              GNUNET_MESSAGE_TYPE_IDENTITY_RESULT_CODE,
187                              struct ResultCodeMessage,
188                              el),
189       GNUNET_MQ_hd_var_size (identity_update,
190                              GNUNET_MESSAGE_TYPE_IDENTITY_UPDATE,
191                              struct UpdateMessage,
192                              el),
193       GNUNET_MQ_handler_end () };
194
195     el->mq =
196       GNUNET_CLIENT_connect (cfg, "identity", handlers, &mq_error_handler, el);
197   }
198   if (NULL == el->mq)
199   {
200     GNUNET_break (0);
201     GNUNET_free (el);
202     return NULL;
203   }
204   el->suffix = GNUNET_strdup (suffix);
205   nlen = strlen (suffix) + 1;
206   env = GNUNET_MQ_msg_extra (req, nlen,
207                              GNUNET_MESSAGE_TYPE_IDENTITY_LOOKUP_BY_SUFFIX);
208   memcpy (&req[1], suffix, nlen);
209   GNUNET_MQ_send (el->mq, env);
210   return el;
211 }
212
213
214 /**
215  * Abort ego lookup attempt.
216  *
217  * @param el handle for lookup to abort
218  */
219 void
220 GNUNET_IDENTITY_ego_lookup_by_suffix_cancel (struct
221                                              GNUNET_IDENTITY_EgoSuffixLookup *el)
222 {
223   GNUNET_MQ_destroy (el->mq);
224   GNUNET_free (el->suffix);
225   GNUNET_free (el);
226 }
227
228
229 /* end of identity_api_suffix_lookup.c */