aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorOmar Tarabai <tarabai@devegypt.com>2014-05-05 17:49:52 +0000
committerOmar Tarabai <tarabai@devegypt.com>2014-05-05 17:49:52 +0000
commit2905ca535539de209dbde292e876e2995bb0c160 (patch)
tree1494346b5e0ee3ecc6b9d8dc42fad30e7efbe9ad /src
parented35aa248e65f947ea436528c3861644dca381da (diff)
downloadgnunet-2905ca535539de209dbde292e876e2995bb0c160.tar.gz
gnunet-2905ca535539de209dbde292e876e2995bb0c160.zip
towards PEERSTORE api
Diffstat (limited to 'src')
-rw-r--r--src/include/gnunet_peerstore_service.h26
-rw-r--r--src/peerstore/peerstore_api.c264
2 files changed, 290 insertions, 0 deletions
diff --git a/src/include/gnunet_peerstore_service.h b/src/include/gnunet_peerstore_service.h
index e8a05100b..91baa3c0f 100644
--- a/src/include/gnunet_peerstore_service.h
+++ b/src/include/gnunet_peerstore_service.h
@@ -37,6 +37,32 @@ extern "C"
37#endif 37#endif
38#endif 38#endif
39 39
40/**
41 * Handle to the peerstore service.
42 */
43struct GNUNET_PEERSTORE_Handle;
44
45/**
46 * Context for add requests
47 */
48struct GNUNET_PEERSTORE_AddContext;
49
50/**
51 * Continuation called with a status result.
52 *
53 * @param cls closure
54 * @param emsg error message, NULL on success
55 */
56typedef void (*GNUNET_PEERSTORE_Continuation)(void *cls,
57 const char *emsg);
58
59/**
60 * Continuation called after an Add is completed
61 *
62 * @param cls closure
63 * @param success #GNUNET_YES / #GNUNET_NO
64 */
65typedef void (*GNUNET_PEERSTORE_AddContinuation)(void *cls, int success);
40 66
41#if 0 /* keep Emacsens' auto-indent happy */ 67#if 0 /* keep Emacsens' auto-indent happy */
42{ 68{
diff --git a/src/peerstore/peerstore_api.c b/src/peerstore/peerstore_api.c
index 02c8d69df..a1e75e6e7 100644
--- a/src/peerstore/peerstore_api.c
+++ b/src/peerstore/peerstore_api.c
@@ -33,15 +33,279 @@
33/************************ DATA STRUCTURES ****************************/ 33/************************ DATA STRUCTURES ****************************/
34/******************************************************************************/ 34/******************************************************************************/
35 35
36/**
37 * Handle to the peerstore service.
38 */
39struct GNUNET_PEERSTORE_Handle
40{
41
42 /**
43 * Our configuration.
44 */
45 const struct GNUNET_CONFIGURATION_Handle *cfg;
46
47 /**
48 * Connection to the service.
49 */
50 struct GNUNET_CLIENT_Connection *client;
51
52 /**
53 * Head of transmission queue.
54 */
55 struct GNUNET_PEERSTORE_AddContext *rc_head;
56
57 /**
58 * Tail of transmission queue.
59 */
60 struct GNUNET_PEERSTORE_AddContext *rc_tail;
61
62 /**
63 * Handle for the current transmission request, or NULL if none is pending.
64 */
65 struct GNUNET_CLIENT_TransmitHandle *th;
66
67 /**
68 * ID for a reconnect task.
69 */
70 GNUNET_SCHEDULER_TaskIdentifier r_task;
71
72 /**
73 * Are we now receiving?
74 */
75 int in_receive;
76
77};
78
79/**
80 * Entry in the transmission queue to PEERSTORE service.
81 *
82 */
83struct GNUNET_PEERSTORE_AddContext
84{
85 /**
86 * This is a linked list.
87 */
88 struct GNUNET_PEERSTORE_AddContext *next;
89
90 /**
91 * This is a linked list.
92 */
93 struct GNUNET_PEERSTORE_AddContext *prev;
94
95 /**
96 * Handle to the PEERSTORE service.
97 */
98 struct GNUNET_PEERSTORE_Handle *h;
99
100 /**
101 * Function to call after request has been transmitted, or NULL.
102 */
103 GNUNET_PEERSTORE_Continuation cont;
104
105 /**
106 * Closure for 'cont'.
107 */
108 void *cont_cls;
109
110 /**
111 * Number of bytes of the request message (follows after this struct).
112 */
113 size_t size;
114
115};
36 116
37/******************************************************************************/ 117/******************************************************************************/
38/*********************** DECLARATIONS *************************/ 118/*********************** DECLARATIONS *************************/
39/******************************************************************************/ 119/******************************************************************************/
40 120
121/**
122 * Close the existing connection to PEERSTORE and reconnect.
123 *
124 * @param h handle to the service
125 */
126static void
127reconnect (struct GNUNET_PEERSTORE_Handle *h);
128
129/**
130 * Check if we have a request pending in the transmission queue and are
131 * able to transmit it right now. If so, schedule transmission.
132 *
133 * @param h handle to the service
134 */
135static void
136trigger_transmit (struct GNUNET_PEERSTORE_Handle *h);
41 137
42/******************************************************************************/ 138/******************************************************************************/
43/******************* CONNECTION FUNCTIONS *********************/ 139/******************* CONNECTION FUNCTIONS *********************/
44/******************************************************************************/ 140/******************************************************************************/
45 141
142/**
143 * Connect to the PEERSTORE service.
144 *
145 * @return NULL on error
146 */
147struct GNUNET_PEERSTORE_Handle *
148GNUNET_PEERSTORE_connect (const struct GNUNET_CONFIGURATION_Handle *cfg)
149{
150 struct GNUNET_CLIENT_Connection *client;
151 struct GNUNET_PEERSTORE_Handle *h;
152
153 client = GNUNET_CLIENT_connect ("peerstore", cfg);
154 if(NULL == client)
155 return NULL;
156 h = GNUNET_new (struct GNUNET_PEERSTORE_Handle);
157 h->client = client;
158 h->cfg = cfg;
159 return h;
160}
161
162/**
163 * Disconnect from the PEERSTORE service
164 *
165 * @param h handle to disconnect
166 */
167void
168GNUNET_PEERSTORE_disconnect(struct GNUNET_PEERSTORE_Handle *h)
169{
170 if (NULL != h->client)
171 {
172 GNUNET_CLIENT_disconnect (h->client);
173 h->client = NULL;
174 }
175 GNUNET_free (h);
176}
177
178/**
179 * Task scheduled to re-try connecting to the PEERSTORE service.
180 *
181 * @param cls the 'struct GNUNET_PEERSTORE_Handle'
182 * @param tc scheduler context
183 */
184static void
185reconnect_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
186{
187 struct GNUNET_PEERSTORE_Handle *h = cls;
188
189 h->r_task = GNUNET_SCHEDULER_NO_TASK;
190 reconnect (h);
191}
192
193/**
194 * Close the existing connection to PEERSTORE and reconnect.
195 *
196 * @param h handle to the service
197 */
198static void
199reconnect (struct GNUNET_PEERSTORE_Handle *h)
200{
201 if (GNUNET_SCHEDULER_NO_TASK != h->r_task)
202 {
203 GNUNET_SCHEDULER_cancel (h->r_task);
204 h->r_task = GNUNET_SCHEDULER_NO_TASK;
205 }
206 if (NULL != h->th)
207 {
208 GNUNET_CLIENT_notify_transmit_ready_cancel (h->th);
209 h->th = NULL;
210 }
211 if (NULL != h->client)
212 {
213 GNUNET_CLIENT_disconnect (h->client);
214 h->client = NULL;
215 }
216 h->in_receive = GNUNET_NO;
217 h->client = GNUNET_CLIENT_connect ("peerstore", h->cfg);
218 if (NULL == h->client)
219 {
220 h->r_task =
221 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS, &reconnect_task,
222 h);
223 return;
224 }
225 trigger_transmit (h);
226}
227
228/**
229 * Transmit the request at the head of the transmission queue
230 * and trigger continuation (if any).
231 *
232 * @param cls the 'struct GNUNET_PEERSTORE_Handle' (with the queue)
233 * @param size size of the buffer (0 on error)
234 * @param buf where to copy the message
235 * @return number of bytes copied to buf
236 */
237static size_t
238do_transmit (void *cls, size_t size, void *buf)
239{
240 struct GNUNET_PEERSTORE_Handle *h = cls;
241 struct GNUNET_PEERSTORE_AddContext *rc = h->rc_head;
242 size_t ret;
243
244 h->th = NULL;
245 if (NULL == rc)
246 return 0; /* request was cancelled in the meantime */
247 if (NULL == buf)
248 {
249 /* PEERSTORE service died */
250 LOG (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK,
251 "Failed to transmit message to `%s' service.\n", "PEERSTORE");
252 GNUNET_CONTAINER_DLL_remove (h->rc_head, h->rc_tail, rc);
253 reconnect (h);
254 if (NULL != rc->cont)
255 rc->cont (rc->cont_cls, _("failed to transmit request (service down?)"));
256 GNUNET_free (rc);
257 return 0;
258 }
259 ret = rc->size;
260 if (size < ret)
261 {
262 /* change in head of queue (i.e. cancel + add), try again */
263 trigger_transmit (h);
264 return 0;
265 }
266 LOG (GNUNET_ERROR_TYPE_DEBUG,
267 "Transmitting request of size %u to `%s' service.\n", ret, "PEERSTORE");
268 memcpy (buf, &rc[1], ret);
269 GNUNET_CONTAINER_DLL_remove (h->rc_head, h->rc_tail, rc);
270 trigger_transmit (h);
271 if (NULL != rc->cont)
272 rc->cont (rc->cont_cls, NULL);
273 GNUNET_free (rc);
274 return ret;
275}
276
277/**
278 * Check if we have a request pending in the transmission queue and are
279 * able to transmit it right now. If so, schedule transmission.
280 *
281 * @param h handle to the service
282 */
283static void
284trigger_transmit (struct GNUNET_PEERSTORE_Handle *h)
285{
286 struct GNUNET_PEERSTORE_AddContext *rc;
287
288 if (NULL == (rc = h->rc_head))
289 return; /* no requests queued */
290 if (NULL != h->th)
291 return; /* request already pending */
292 if (NULL == h->client)
293 {
294 /* disconnected, try to reconnect */
295 reconnect (h);
296 return;
297 }
298 h->th =
299 GNUNET_CLIENT_notify_transmit_ready (h->client, rc->size,
300 GNUNET_TIME_UNIT_FOREVER_REL,
301 GNUNET_YES,
302 &do_transmit, h);
303}
304
305/******************************************************************************/
306/******************* STORE FUNCTIONS *********************/
307/******************************************************************************/
308
309
46 310
47/* end of peerstore_api.c */ 311/* end of peerstore_api.c */