-improve UDP logging
[oweals/gnunet.git] / src / rps / rps_api.c
1 /*
2      This file is part of GNUnet.
3      Copyright (C) 
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., 59 Temple Place - Suite 330,
18      Boston, MA 02111-1307, USA.
19 */
20
21 /**
22  * @file rps/rps_api.c
23  * @brief API for rps
24  * @author Julius Bünger
25  */
26 #include "platform.h"
27 #include "gnunet_util_lib.h"
28 #include "rps.h"
29 #include "gnunet_rps_service.h"
30
31 /**
32  * Handler to handle requests from a client.
33  */
34 struct GNUNET_RPS_Handle
35 {
36   /**
37    * The handle to the client configuration.
38    */
39   const struct GNUNET_CONFIGURATION_Handle *cfg;
40
41   /**
42    * The connection to the client.
43    */
44   struct GNUNET_CLIENT_Connection *conn;
45
46   /**
47    * The message queue to the client.
48    */
49   struct GNUNET_MQ_Handle *mq;
50 };
51
52
53 /**
54  * Handler to single requests from the client.
55  */
56 struct GNUNET_RPS_Request_Handle
57 {
58   /**
59    * The client issuing the request.
60    */
61   struct GNUNET_RPS_Handle *h;
62
63   /**
64    * The nuber of the request.
65    */
66   uint64_t n;
67
68   /**
69    * The callback to be called when we receive an answer.
70    */
71   GNUNET_RPS_NotifyReadyCB ready_cb;
72
73   /**
74    * The closure for the callback.
75    */
76   void *ready_cb_cls;
77 };
78
79
80 /**
81  * Array of Request_Handles.
82  */
83 struct GNUNET_RPS_Request_Handle *req_handlers = NULL;
84
85 /**
86  * Current length of req_handlers.
87  */
88 unsigned int req_handlers_size = 0;
89
90
91 /**
92  * Struct used to pack the callback, its closure (provided by the caller)
93  * and the connection handler to the service to pass it to a callback function.
94  */
95 struct cb_cls_pack
96 {
97   /**
98    * Callback provided by the client
99    */
100   GNUNET_RPS_NotifyReadyCB cb;
101
102   /**
103    * Closure provided by the client
104    */
105   void *cls;
106
107   /**
108    * Handle to the service connection
109    */
110  struct GNUNET_CLIENT_Connection *service_conn;
111 };
112
113
114 /**
115  * This function is called, when the service replies to our request.
116  * It calls the callback the caller gave us with the provided closure
117  * and disconnects afterwards.
118  *
119  * @param cls the closure
120  * @param message the message
121  */
122   static void
123 handle_reply (void *cls,
124               const struct GNUNET_MessageHeader *message)
125 {
126   struct GNUNET_RPS_CS_ReplyMessage *msg;
127   //struct cb_cls_pack *pack;
128   //struct GNUNET_RPS_Handle *h;
129   struct GNUNET_PeerIdentity *peers;
130   struct GNUNET_RPS_Request_Handle *rh;
131
132   /* Give the peers back */
133   msg = (struct GNUNET_RPS_CS_ReplyMessage *) message;
134   //pack = (struct cb_cls_pack *) cls;
135   //h = (struct GNUNET_RPS_Handle *) cls;
136   peers = (struct GNUNET_PeerIdentity *) &msg[1];
137   rh = &req_handlers[msg->n];
138   rh->ready_cb((rh)->ready_cb_cls, msg->num_peers, peers);
139
140   /* Disconnect */
141   //GNUNET_CLIENT_disconnect(pack->service_conn);
142 }
143
144
145 /**
146  * Error handler for mq.
147  *
148  * This function is called whan mq encounters an error.
149  * Until now mq doesn't provide useful error messages.
150  *
151  * @param cls the closure
152  * @param error error code without specyfied meaning
153  */
154   static void
155 mq_error_handler (void *cls, enum GNUNET_MQ_Error error)
156 {
157   //TODO LOG
158 }
159
160 /**
161  * Connect to the rps service
162  *
163  * @param cfg configuration to use
164  * @return a handle to the service
165  */
166   struct GNUNET_RPS_Handle *
167 GNUNET_RPS_connect (const struct GNUNET_CONFIGURATION_Handle *cfg)
168 {
169   struct GNUNET_RPS_Handle *h;
170   //struct GNUNET_RPS_Request_Handle *rh;
171   static const struct GNUNET_MQ_MessageHandler mq_handlers[] = {
172     {&handle_reply, GNUNET_MESSAGE_TYPE_RPS_CS_REPLY, 0},
173     GNUNET_MQ_HANDLERS_END
174   };
175
176   h = GNUNET_new(struct GNUNET_RPS_Handle);
177   //h->cfg = GNUNET_new(struct GNUNET_CONFIGURATION_Handle);
178   //*h->cfg = *cfg;
179   h->cfg = cfg; // FIXME |^
180   h->conn = GNUNET_CLIENT_connect("rps", cfg);
181   h->mq = GNUNET_MQ_queue_for_connection_client(h->conn,
182                                                 mq_handlers,
183                                                 mq_error_handler, // TODO implement
184                                                 h);
185
186   return h;
187 }
188
189
190 /**
191  * Request n random peers.
192  *
193  * @param h handle to the rps service
194  * @param n number of peers we want to receive
195  * @param ready_cb the callback called when the peers are available
196  * @param cls closure given to the callback
197  * @return a handle to cancel this request
198  */
199   struct GNUNET_RPS_Request_Handle *
200 GNUNET_RPS_request_peers (struct GNUNET_RPS_Handle *h, uint32_t n,
201                           GNUNET_RPS_NotifyReadyCB ready_cb,
202                           void *cls)
203 {
204   struct GNUNET_RPS_Request_Handle *rh;
205   struct GNUNET_MQ_Envelope *ev;
206   struct GNUNET_RPS_CS_RequestMessage *msg;
207
208   // assert func != NULL
209   rh = GNUNET_new (struct GNUNET_RPS_Request_Handle);
210   rh->h = h;
211   rh->n = req_handlers_size; // TODO ntoh
212   rh->ready_cb = ready_cb;
213   rh->ready_cb_cls = cls;
214
215   GNUNET_array_append (req_handlers, req_handlers_size, *rh);
216   //memcpy(&req_handlers[req_handlers_size-1], rh, sizeof(struct GNUNET_RPS_Request_Handle));
217
218   ev = GNUNET_MQ_msg (msg, GNUNET_MESSAGE_TYPE_RPS_CS_REQUEST);
219   msg->num_peers = htonl (n);
220   msg->n = rh->n;
221   GNUNET_MQ_send (h->mq, ev);
222   return rh;
223 }
224
225
226 /**
227  * Seed rps service with peerIDs.
228  *
229  * @param h handle to the rps service
230  * @param n number of peers to seed
231  * @param ids the ids of the peers seeded
232  */
233   void
234 GNUNET_RPS_seed_ids (struct GNUNET_RPS_Handle *h, uint64_t n,
235                      const struct GNUNET_PeerIdentity * ids)
236 {
237   uint32_t size_needed;
238   uint32_t num_peers_max;
239   const struct GNUNET_PeerIdentity *tmp_peer_pointer;
240   struct GNUNET_MQ_Envelope *ev;
241   struct GNUNET_RPS_CS_SeedMessage *msg;
242
243   /* The actual size the message occupies */
244   size_needed = sizeof (struct GNUNET_RPS_CS_SeedMessage) +
245     n * sizeof (struct GNUNET_PeerIdentity);
246   /* The number of peers that fits in one message together with
247    * the respective header */
248   num_peers_max = (GNUNET_SERVER_MAX_MESSAGE_SIZE -
249       sizeof (struct GNUNET_RPS_CS_SeedMessage)) /
250     sizeof (struct GNUNET_PeerIdentity);
251   tmp_peer_pointer = ids;
252
253   while (GNUNET_SERVER_MAX_MESSAGE_SIZE < size_needed)
254   {
255     ev = GNUNET_MQ_msg_extra (msg, num_peers_max * sizeof (struct GNUNET_PeerIdentity),
256         GNUNET_MESSAGE_TYPE_RPS_CS_SEED);
257     msg->num_peers = ntohl (num_peers_max);
258     memcpy (&msg[1], tmp_peer_pointer, num_peers_max * sizeof (struct GNUNET_PeerIdentity));
259     GNUNET_MQ_send (h->mq, ev);
260
261     n -= num_peers_max;
262     size_needed = sizeof (struct GNUNET_RPS_CS_SeedMessage) +
263                   n * sizeof (struct GNUNET_PeerIdentity);
264     /* Set pointer to beginning of next block of num_peers_max peers */
265     tmp_peer_pointer = &ids[num_peers_max];
266   }
267
268   ev = GNUNET_MQ_msg_extra (msg, n * sizeof (struct GNUNET_PeerIdentity),
269                             GNUNET_MESSAGE_TYPE_RPS_CS_SEED);
270   msg->num_peers = GNUNET_htonll (n);
271   memcpy (&msg[1], tmp_peer_pointer, n * sizeof (struct GNUNET_PeerIdentity));
272   GNUNET_MQ_send (h->mq, ev);
273 }
274
275
276 /**
277  * Cancle an issued request.
278  *
279  * @param rh request handle of request to cancle
280  */
281   void
282 GNUNET_RPS_request_cancel (struct GNUNET_RPS_Request_Handle *rh)
283 {
284   // TODO
285 }
286
287
288 /**
289  * Disconnect from the rps service
290  *
291  * @param h the handle to the rps service
292  */
293   void
294 GNUNET_RPS_disconnect (struct GNUNET_RPS_Handle *h)
295 {
296   if ( NULL != h->conn )
297     GNUNET_CLIENT_disconnect (h->conn);
298 }
299
300
301 /* end of rps_api.c */