-skeleton for identity service
[oweals/gnunet.git] / src / identity / identity_api.c
1 /*
2      This file is part of GNUnet.
3      (C) 2013 Christian Grothoff (and other contributing authors)
4
5      GNUnet is free software; you can redistribute it and/or modify
6      it under the terms of the GNU General Public Liceidentity 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 Liceidentity for more details.
14
15      You should have received a copy of the GNU General Public Liceidentity
16      along with GNUnet; see the file COPYING.  If not, write to the
17      Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18      Boston, MA 02111-1307, USA.
19 */
20
21 /**
22  * @file identity/identity_api.c
23  * @brief api to get information from the network size estimation service
24  * @author Nathan Evans
25  */
26 #include "platform.h"
27 #include "gnunet_client_lib.h"
28 #include "gnunet_constants.h"
29 #include "gnunet_container_lib.h"
30 #include "gnunet_arm_service.h"
31 #include "gnunet_hello_lib.h"
32 #include "gnunet_protocols.h"
33 #include "gnunet_server_lib.h"
34 #include "gnunet_time_lib.h"
35 #include "gnunet_identity_service.h"
36 #include "identity.h"
37
38 #define LOG(kind,...) GNUNET_log_from (kind, "identity-api",__VA_ARGS__)
39
40 /**
41  * Handle for the service.
42  */
43 struct GNUNET_IDENTITY_Handle
44 {
45   /**
46    * Configuration to use.
47    */
48   const struct GNUNET_CONFIGURATION_Handle *cfg;
49
50   /**
51    * Socket (if available).
52    */
53   struct GNUNET_CLIENT_Connection *client;
54
55   /**
56    * Currently pending transmission request.
57    */
58   struct GNUNET_CLIENT_TransmitHandle *th;
59
60   /**
61    * Task doing exponential back-off trying to reconnect.
62    */
63   GNUNET_SCHEDULER_TaskIdentifier reconnect_task;
64
65   /**
66    * Time for next connect retry.
67    */
68   struct GNUNET_TIME_Relative reconnect_delay;
69
70 };
71
72
73 /**
74  * Try again to connect to network size estimation service.
75  *
76  * @param cls the handle to the transport service
77  * @param tc scheduler context
78  */
79 static void
80 reconnect (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc);
81
82
83 /**
84  * Type of a function to call when we receive a message
85  * from the service.
86  *
87  * @param cls closure
88  * @param msg message received, NULL on timeout or fatal error
89  */
90 static void
91 message_handler (void *cls, const struct GNUNET_MessageHeader *msg)
92 {
93   struct GNUNET_IDENTITY_Handle *h = cls;
94   const struct GNUNET_IDENTITY_ClientMessage *client_msg;
95
96   if (msg == NULL)
97   {
98     /* Error, timeout, death */
99     GNUNET_CLIENT_disconnect (h->client);
100     h->client = NULL;
101     h->reconnect_task =
102         GNUNET_SCHEDULER_add_delayed (h->reconnect_delay, &reconnect, h);
103     return;
104   }
105   // FIXME: process...
106   GNUNET_CLIENT_receive (h->client, &message_handler, h,
107                          GNUNET_TIME_UNIT_FOREVER_REL);
108 }
109
110
111
112 /**
113  * Reschedule a connect attempt to the service.
114  *
115  * @param h transport service to reconnect
116  */
117 static void
118 reschedule_connect (struct GNUNET_IDENTITY_Handle *h)
119 {
120   GNUNET_assert (h->reconnect_task == GNUNET_SCHEDULER_NO_TASK);
121
122   if (NULL != h->th)
123   {
124     GNUNET_CLIENT_notify_transmit_ready_cancel (h->th);
125     h->th = NULL;
126   }
127   if (NULL != h->client)
128   {
129     GNUNET_CLIENT_disconnect (h->client);
130     h->client = NULL;
131   }
132
133   LOG (GNUNET_ERROR_TYPE_DEBUG,
134        "Scheduling task to reconnect to identity service in %llu ms.\n",
135        h->reconnect_delay.rel_value);
136   h->reconnect_task =
137       GNUNET_SCHEDULER_add_delayed (h->reconnect_delay, &reconnect, h);
138   h->reconnect_delay = GNUNET_TIME_STD_BACKOFF (h->reconnect_delay);
139 }
140
141
142 /**
143  * Transmit START message to service.
144  *
145  * @param cls unused
146  * @param size number of bytes available in buf
147  * @param buf where to copy the message
148  * @return number of bytes copied to buf
149  */
150 static size_t
151 send_start (void *cls, size_t size, void *buf)
152 {
153   return sizeof (struct GNUNET_MessageHeader);
154 }
155
156
157 /**
158  * Try again to connect to network size estimation service.
159  *
160  * @param cls the handle to the transport service
161  * @param tc scheduler context
162  */
163 static void
164 reconnect (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
165 {
166   struct GNUNET_IDENTITY_Handle *h = cls;
167
168   h->reconnect_task = GNUNET_SCHEDULER_NO_TASK;
169   if ((tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN) != 0)
170   {
171     /* shutdown, just give up */
172     return;
173   }
174   LOG (GNUNET_ERROR_TYPE_DEBUG,
175        "Connecting to network size estimation service.\n");
176   GNUNET_assert (h->client == NULL);
177   h->client = GNUNET_CLIENT_connect ("identity", h->cfg);
178   GNUNET_assert (h->client != NULL);
179
180   h->th =
181       GNUNET_CLIENT_notify_transmit_ready (h->client,
182                                            sizeof (struct GNUNET_MessageHeader),
183                                            GNUNET_TIME_UNIT_FOREVER_REL,
184                                            GNUNET_NO, &send_start, h);
185   GNUNET_assert (h->th != NULL);
186 }
187
188
189 /**
190  * Connect to the identity service.
191  *
192  * @param cfg the configuration to use
193  * @param cb function to call on all identity events, can be NULL
194  * @param cb_cls closure for 'cb'
195  * @return handle to use
196  */
197 struct GNUNET_IDENTITY_Handle *
198 GNUNET_IDENTITY_connect (const struct GNUNET_CONFIGURATION_Handle *cfg,
199                          GNUNET_IDENTITY_Callback cb,
200                          void *cb_cls)
201 {
202   struct GNUNET_IDENTITY_Handle *ret;
203
204   ret = GNUNET_malloc (sizeof (struct GNUNET_IDENTITY_Handle));
205   ret->cfg = cfg;
206   ret->reconnect_delay = GNUNET_TIME_UNIT_ZERO;
207   ret->reconnect_task = GNUNET_SCHEDULER_add_now (&reconnect, ret);
208   return ret;
209 }
210
211
212 /**
213  * Disconnect from identity service
214  *
215  * @param h handle to destroy
216  */
217 void
218 GNUNET_IDENTITY_disconnect (struct GNUNET_IDENTITY_Handle *h)
219 {
220   GNUNET_assert (NULL != h);
221   if (h->reconnect_task != GNUNET_SCHEDULER_NO_TASK)
222   {
223     GNUNET_SCHEDULER_cancel (h->reconnect_task);
224     h->reconnect_task = GNUNET_SCHEDULER_NO_TASK;
225   }
226   if (h->th != NULL)
227   {
228     GNUNET_CLIENT_notify_transmit_ready_cancel (h->th);
229     h->th = NULL;
230   }
231   if (h->client != NULL)
232   {
233     GNUNET_CLIENT_disconnect (h->client);
234     h->client = NULL;
235   }
236   GNUNET_free (h);
237 }
238
239 /* end of identity_api.c */