diff options
Diffstat (limited to 'src/regex/regex_api_search.c')
-rw-r--r-- | src/regex/regex_api_search.c | 215 |
1 files changed, 215 insertions, 0 deletions
diff --git a/src/regex/regex_api_search.c b/src/regex/regex_api_search.c new file mode 100644 index 000000000..728e12beb --- /dev/null +++ b/src/regex/regex_api_search.c | |||
@@ -0,0 +1,215 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet | ||
3 | Copyright (C) 2012, 2013, 2016 GNUnet e.V. | ||
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., 51 Franklin Street, Fifth Floor, | ||
18 | Boston, MA 02110-1301, USA. | ||
19 | */ | ||
20 | /** | ||
21 | * @file regex/regex_api_search.c | ||
22 | * @brief access regex service to discover | ||
23 | * peers using matching strings | ||
24 | * @author Maximilian Szengel | ||
25 | * @author Christian Grothoff | ||
26 | */ | ||
27 | #include "platform.h" | ||
28 | #include "gnunet_protocols.h" | ||
29 | #include "gnunet_util_lib.h" | ||
30 | #include "gnunet_regex_service.h" | ||
31 | #include "regex_ipc.h" | ||
32 | |||
33 | #define LOG(kind,...) GNUNET_log_from (kind, "regex-api",__VA_ARGS__) | ||
34 | |||
35 | |||
36 | /** | ||
37 | * Handle to store data about a regex search. | ||
38 | */ | ||
39 | struct GNUNET_REGEX_Search | ||
40 | { | ||
41 | /** | ||
42 | * Connection to the regex service. | ||
43 | */ | ||
44 | struct GNUNET_CLIENT_Connection *client; | ||
45 | |||
46 | /** | ||
47 | * Our configuration. | ||
48 | */ | ||
49 | const struct GNUNET_CONFIGURATION_Handle *cfg; | ||
50 | |||
51 | /** | ||
52 | * Function to call with results. | ||
53 | */ | ||
54 | GNUNET_REGEX_Found callback; | ||
55 | |||
56 | /** | ||
57 | * Closure for @e callback. | ||
58 | */ | ||
59 | void *callback_cls; | ||
60 | |||
61 | /** | ||
62 | * Search message to transmit to the service. | ||
63 | */ | ||
64 | struct RegexSearchMessage *msg; | ||
65 | }; | ||
66 | |||
67 | |||
68 | /** | ||
69 | * We got a response or disconnect after asking regex | ||
70 | * to do the search. Handle it. | ||
71 | * | ||
72 | * @param cls the `struct GNUNET_REGEX_Search` to retry | ||
73 | * @param msg NULL on disconnect | ||
74 | */ | ||
75 | static void | ||
76 | handle_search_response (void *cls, | ||
77 | const struct GNUNET_MessageHeader *msg); | ||
78 | |||
79 | |||
80 | /** | ||
81 | * Try sending the search request to regex. On | ||
82 | * errors (i.e. regex died), try again. | ||
83 | * | ||
84 | * @param s the search to retry | ||
85 | */ | ||
86 | static void | ||
87 | retry_search (struct GNUNET_REGEX_Search *s) | ||
88 | { | ||
89 | GNUNET_assert (NULL != s->client); | ||
90 | GNUNET_assert (GNUNET_OK == | ||
91 | GNUNET_CLIENT_transmit_and_get_response (s->client, | ||
92 | &s->msg->header, | ||
93 | GNUNET_TIME_UNIT_FOREVER_REL, | ||
94 | GNUNET_YES, | ||
95 | &handle_search_response, | ||
96 | s)); | ||
97 | } | ||
98 | |||
99 | |||
100 | /** | ||
101 | * We got a response or disconnect after asking regex | ||
102 | * to do the search. Handle it. | ||
103 | * | ||
104 | * @param cls the `struct GNUNET_REGEX_Search` to handle reply for | ||
105 | * @param msg NULL on disconnect, otherwise presumably a response | ||
106 | */ | ||
107 | static void | ||
108 | handle_search_response (void *cls, | ||
109 | const struct GNUNET_MessageHeader *msg) | ||
110 | { | ||
111 | struct GNUNET_REGEX_Search *s = cls; | ||
112 | const struct ResultMessage *result; | ||
113 | uint16_t size; | ||
114 | uint16_t gpl; | ||
115 | uint16_t ppl; | ||
116 | |||
117 | if (NULL == msg) | ||
118 | { | ||
119 | GNUNET_CLIENT_disconnect (s->client); | ||
120 | s->client = GNUNET_CLIENT_connect ("regex", s->cfg); | ||
121 | retry_search (s); | ||
122 | return; | ||
123 | } | ||
124 | size = ntohs (msg->size); | ||
125 | if ( (GNUNET_MESSAGE_TYPE_REGEX_RESULT == ntohs (msg->type)) && | ||
126 | (size >= sizeof (struct ResultMessage)) ) | ||
127 | { | ||
128 | result = (const struct ResultMessage *) msg; | ||
129 | gpl = ntohs (result->get_path_length); | ||
130 | ppl = ntohs (result->put_path_length); | ||
131 | if (size == (sizeof (struct ResultMessage) + | ||
132 | (gpl + ppl) * sizeof (struct GNUNET_PeerIdentity))) | ||
133 | { | ||
134 | const struct GNUNET_PeerIdentity *pid; | ||
135 | |||
136 | GNUNET_CLIENT_receive (s->client, | ||
137 | &handle_search_response, s, | ||
138 | GNUNET_TIME_UNIT_FOREVER_REL); | ||
139 | pid = &result->id; | ||
140 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
141 | "Got regex result %s\n", | ||
142 | GNUNET_i2s (pid)); | ||
143 | s->callback (s->callback_cls, | ||
144 | pid, | ||
145 | &pid[1], gpl, | ||
146 | &pid[1 + gpl], ppl); | ||
147 | return; | ||
148 | } | ||
149 | } | ||
150 | GNUNET_break (0); | ||
151 | GNUNET_CLIENT_disconnect (s->client); | ||
152 | s->client = GNUNET_CLIENT_connect ("regex", s->cfg); | ||
153 | retry_search (s); | ||
154 | } | ||
155 | |||
156 | |||
157 | /** | ||
158 | * Search for a peer offering a regex matching certain string in the DHT. | ||
159 | * The search runs until #GNUNET_REGEX_search_cancel() is called, even if results | ||
160 | * are returned. | ||
161 | * | ||
162 | * @param cfg configuration to use | ||
163 | * @param string String to match against the regexes in the DHT. | ||
164 | * @param callback Callback for found peers. | ||
165 | * @param callback_cls Closure for @c callback. | ||
166 | * @return Handle to stop search and free resources. | ||
167 | * Must be freed by calling #GNUNET_REGEX_search_cancel(). | ||
168 | */ | ||
169 | struct GNUNET_REGEX_Search * | ||
170 | GNUNET_REGEX_search (const struct GNUNET_CONFIGURATION_Handle *cfg, | ||
171 | const char *string, | ||
172 | GNUNET_REGEX_Found callback, | ||
173 | void *callback_cls) | ||
174 | { | ||
175 | struct GNUNET_REGEX_Search *s; | ||
176 | size_t slen; | ||
177 | |||
178 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
179 | "Starting regex search for %s\n", | ||
180 | string); | ||
181 | slen = strlen (string) + 1; | ||
182 | s = GNUNET_new (struct GNUNET_REGEX_Search); | ||
183 | s->cfg = cfg; | ||
184 | s->client = GNUNET_CLIENT_connect ("regex", cfg); | ||
185 | if (NULL == s->client) | ||
186 | { | ||
187 | GNUNET_free (s); | ||
188 | return NULL; | ||
189 | } | ||
190 | s->callback = callback; | ||
191 | s->callback_cls = callback_cls; | ||
192 | s->msg = GNUNET_malloc (sizeof (struct RegexSearchMessage) + slen); | ||
193 | s->msg->header.type = htons (GNUNET_MESSAGE_TYPE_REGEX_SEARCH); | ||
194 | s->msg->header.size = htons (sizeof (struct RegexSearchMessage) + slen); | ||
195 | memcpy (&s->msg[1], string, slen); | ||
196 | retry_search (s); | ||
197 | return s; | ||
198 | } | ||
199 | |||
200 | |||
201 | /** | ||
202 | * Stop search and free all data used by a #GNUNET_REGEX_search() call. | ||
203 | * | ||
204 | * @param s Handle returned by a previous #GNUNET_REGEX_search() call. | ||
205 | */ | ||
206 | void | ||
207 | GNUNET_REGEX_search_cancel (struct GNUNET_REGEX_Search *s) | ||
208 | { | ||
209 | GNUNET_CLIENT_disconnect (s->client); | ||
210 | GNUNET_free (s->msg); | ||
211 | GNUNET_free (s); | ||
212 | } | ||
213 | |||
214 | |||
215 | /* end of regex_api.c */ | ||