Added test mockup
[oweals/gnunet.git] / src / mesh / mesh_api_new.c
1 /*
2      This file is part of GNUnet.
3      (C) 2011 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 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 mesh/mesh_api_new.c
23  * @brief mesh api: client implementation of mesh service
24  * @author Bartlomiej Polot
25  */
26
27 #ifdef __cplusplus
28
29 extern "C"
30 {
31 #if 0                           /* keep Emacsens' auto-indent happy */
32 }
33 #endif
34 #endif
35
36
37 #include "platform.h"
38 #include "gnunet_common.h"
39 #include "gnunet_client_lib.h"
40 #include "gnunet_util_lib.h"
41 #include "gnunet_mesh_service_new.h"
42 #include "mesh.h"
43
44 /**
45  * Opaque handle to the service.
46  */
47 struct GNUNET_MESH_Handle {
48     /**
49      * Handle to the server connection, to send messages later
50      */
51     struct GNUNET_CLIENT_Connection             *mesh;
52
53     /**
54      * Set of handlers used for processing incoming messages in the tunnels
55      */
56     const struct GNUNET_MESH_MessageHandler     *message_handlers;
57     int                                         n_handlers;
58
59     /**
60      * Set of applications that should be claimed to be offered at this node.
61      * Note that this is just informative, the appropiate handlers must be
62      * registered independently and the mapping is up to the developer of the
63      * client application.
64      */
65     const GNUNET_MESH_ApplicationType           *applications;
66     int                                         n_applications;
67
68     /**
69      * Double linked list of the tunnels this client is connected to.
70      */
71     struct GNUNET_MESH_Tunnel                   *head;
72     struct GNUNET_MESH_Tunnel                   *tail;
73
74     /**
75      * Callback for tunnel disconnection
76      */
77     GNUNET_MESH_TunnelEndHandler                *cleaner;
78
79     /**
80      * Closure for all the handlers given by the client
81      */
82     void                                        *cls;
83 };
84
85 /**
86  * Opaque handle to a tunnel.
87  */
88 struct GNUNET_MESH_Tunnel {
89     /**
90      * Owner of the tunnel, either local or remote
91      */
92     GNUNET_PEER_Id                              owner;
93
94     /**
95      * Callback to execute when peers connect to the tunnel
96      */
97     GNUNET_MESH_TunnelConnectHandler            connect_handler;
98
99     /**
100      * Callback to execute when peers disconnect to the tunnel
101      */
102     GNUNET_MESH_TunnelDisconnectHandler         disconnect_handler;
103
104     /**
105      * All peers added to the tunnel
106      */
107     GNUNET_PEER_Id                              *peers;
108
109     /**
110      * Closure for the connect/disconnect handlers
111      */
112     void                                        *cls;
113 };
114
115 struct GNUNET_MESH_TransmitHandle {
116     // TODO
117 };
118
119
120 /**
121  * Function called to notify a client about the socket begin ready to queue more
122  * data.  "buf" will be NULL and "size" zero if the socket was closed for
123  * writing in the meantime.
124  *
125  * @param cls closure
126  * @param size number of bytes available in buf
127  * @param buf where the callee should write the message
128  * @return number of bytes written to buf
129  */
130 size_t 
131 send_connect_packet (void *cls, size_t size, void *buf) {
132     struct GNUNET_MESH_Handle           *h;
133     struct GNUNET_MESH_ClientConnect    *msg;
134     uint16_t                            *types;
135     int                                 ntypes;
136     GNUNET_MESH_ApplicationType         *apps;
137     int                                 napps;
138
139     if(0 == size || buf == NULL) {
140         /* TODO treat error / retry */
141         return 0;
142     }
143     if(sizeof(struct GNUNET_MessageHeader) > size) {
144         /* TODO treat error / retry */
145         return 0;
146     }
147     msg = (struct GNUNET_MESH_ClientConnect *) buf;
148     h = (struct GNUNET_MESH_Handle *) cls;
149     msg->header.type = GNUNET_MESSAGE_TYPE_MESH_LOCAL_CONNECT;
150     for(ntypes = 0, types = NULL; h->message_handlers[ntypes].type; ntypes++) {
151         types = GNUNET_realloc(types, sizeof(uint16_t) * (ntypes + 1));
152         types[ntypes] = h->message_handlers[ntypes].type;
153     }
154     for(napps = 0, apps = NULL; h->applications[napps]; napps++) {
155         apps = GNUNET_realloc(apps,
156                               sizeof(GNUNET_MESH_ApplicationType) *
157                                 (napps + 1));
158         apps[napps] = h->applications[napps];
159     }
160     msg->header.size = sizeof(struct GNUNET_MESH_ClientConnect) +
161                         sizeof(uint16_t) * ntypes +
162                         sizeof(GNUNET_MESH_ApplicationType) * napps;
163     if(msg->header.size > size) {
164         /* TODO treat error / retry */
165         return 0;
166     }
167     memcpy(&msg[1], types, sizeof(uint16_t) * ntypes);
168     memcpy(&msg[1] + sizeof(uint16_t) * ntypes,
169            apps,
170            sizeof(GNUNET_MESH_ApplicationType) * napps);
171     return msg->header.size;
172 }
173
174
175
176 /**
177  * Connect to the mesh service.
178  *
179  * @param cfg configuration to use
180  * @param cls closure for the various callbacks that follow
181  *            (including handlers in the handlers array)
182  * @param cleaner function called when an *inbound* tunnel is destroyed
183  * @param handlers callbacks for messages we care about, NULL-terminated
184  *                 note that the mesh is allowed to drop notifications about
185  *                 inbound messages if the client does not process them fast
186  *                 enough (for this notification type, a bounded queue is used)
187  * @param stypes Application Types the client claims to offer
188  * @return handle to the mesh service 
189  *         NULL on error (in this case, init is never called)
190  */
191 struct GNUNET_MESH_Handle *
192 GNUNET_MESH_connect (const struct GNUNET_CONFIGURATION_Handle *cfg,
193                      void *cls,
194                      GNUNET_MESH_TunnelEndHandler cleaner,
195                      const struct GNUNET_MESH_MessageHandler *handlers,
196                      const GNUNET_MESH_ApplicationType *stypes) {
197     struct GNUNET_MESH_Handle           *h;
198     size_t                              size;
199
200     h = GNUNET_malloc(sizeof(struct GNUNET_MESH_Handle));
201
202
203     h->cleaner = cleaner;
204     h->mesh = GNUNET_CLIENT_connect("mesh", cfg);
205     if(h->mesh == NULL) {
206         GNUNET_free(h);
207         return NULL;
208     }
209     h->cls = cls;
210     h->message_handlers = handlers;
211     h->applications = stypes;
212
213     for(h->n_handlers = 0; handlers[h->n_handlers].type; h->n_handlers++);
214     for(h->n_applications = 0; stypes[h->n_applications]; h->n_applications++);
215     h->n_handlers--;
216     h->n_applications--;
217
218     size = sizeof(struct GNUNET_MESH_ClientConnect);
219     size += h->n_handlers * sizeof(uint16_t);
220     size += h->n_applications * sizeof(GNUNET_MESH_ApplicationType);
221
222     GNUNET_CLIENT_notify_transmit_ready(h->mesh,
223                                         size,
224                                         GNUNET_TIME_relative_get_forever(),
225                                         GNUNET_YES,
226                                         &send_connect_packet,
227                                         (void *)h);
228
229     return h;
230 }
231
232
233 /**
234  * Disconnect from the mesh service.
235  *
236  * @param handle connection to mesh to disconnect
237  */
238 void GNUNET_MESH_disconnect (struct GNUNET_MESH_Handle *handle) {
239     
240     GNUNET_free(handle);
241     return;
242 }
243
244
245 /**
246  * Create a new tunnel (we're initiator and will be allowed to add/remove peers
247  * and to broadcast).
248  *
249  * @param h mesh handle
250  * @param connect_handler function to call when peers are actually connected
251  * @param disconnect_handler function to call when peers are disconnected
252  * @param handler_cls closure for connect/disconnect handlers
253  */
254 struct GNUNET_MESH_Tunnel *
255 GNUNET_MESH_tunnel_create (struct GNUNET_MESH_Handle *h,
256                            GNUNET_MESH_TunnelConnectHandler
257                            connect_handler,
258                            GNUNET_MESH_TunnelDisconnectHandler
259                            disconnect_handler,
260                            void *handler_cls) {
261     struct GNUNET_MESH_Tunnel           *tunnel;
262
263     tunnel = GNUNET_malloc(sizeof(struct GNUNET_MESH_Tunnel));
264
265     tunnel->connect_handler = connect_handler;
266     tunnel->disconnect_handler = disconnect_handler;
267     tunnel->peers = NULL;
268     tunnel->cls = handler_cls;
269
270     return tunnel;
271 }
272
273
274 /**
275  * Request that a peer should be added to the tunnel.  The existing
276  * connect handler will be called ONCE with either success or failure.
277  *
278  * @param tunnel handle to existing tunnel
279  * @param timeout how long to try to establish a connection
280  * @param peer peer to add
281  */
282 void
283 GNUNET_MESH_peer_request_connect_add (struct GNUNET_MESH_Tunnel *tunnel,
284                                       struct GNUNET_TIME_Relative timeout,
285                                       const struct GNUNET_PeerIdentity *peer) {
286     static GNUNET_PEER_Id       peer_id;
287     
288     peer_id = GNUNET_PEER_intern(peer);
289     
290     /* FIXME ACTUALLY DO STUFF */
291     tunnel->peers = &peer_id;
292     tunnel->connect_handler(tunnel->cls, peer, NULL);
293     return;
294 }
295
296
297 /**
298  * Request that a peer should be removed from the tunnel.  The existing
299  * disconnect handler will be called ONCE if we were connected.
300  *
301  * @param tunnel handle to existing tunnel
302  * @param peer peer to remove
303  */
304 void
305 GNUNET_MESH_peer_request_connect_del (struct GNUNET_MESH_Tunnel *tunnel,
306                                       const struct GNUNET_PeerIdentity *peer) {
307     /* FIXME ACTUALLY DO STUFF */
308     tunnel->peers = NULL;
309     tunnel->disconnect_handler(tunnel->cls, peer);
310     return;
311 }
312
313
314 /**
315  * Request that the mesh should try to connect to a peer supporting the given
316  * message type.
317  *
318  * @param tunnel handle to existing tunnel
319  * @param timeout how long to try to establish a connection
320  * @param app_type application type that must be supported by the peer (MESH
321  *                 should discover peer in proximity handling this type)
322  */
323 void
324 GNUNET_MESH_peer_request_connect_by_type (struct GNUNET_MESH_Tunnel *tunnel,
325                                           struct GNUNET_TIME_Relative timeout,
326                                           GNUNET_MESH_ApplicationType
327                                           app_type) {
328     return;
329 }
330
331
332 /**
333  * Ask the mesh to call "notify" once it is ready to transmit the
334  * given number of bytes to the specified "target".  If we are not yet
335  * connected to the specified peer, a call to this function will cause
336  * us to try to establish a connection.
337  *
338  * @param tunnel tunnel to use for transmission
339  * @param cork is corking allowed for this transmission?
340  * @param priority how important is the message?
341  * @param maxdelay how long can the message wait?
342  * @param target destination for the message,
343  *               NULL for multicast to all tunnel targets 
344  * @param notify_size how many bytes of buffer space does notify want?
345  * @param notify function to call when buffer space is available;
346  *        will be called with NULL on timeout or if the overall queue
347  *        for this peer is larger than queue_size and this is currently
348  *        the message with the lowest priority
349  * @param notify_cls closure for notify
350  * @return non-NULL if the notify callback was queued,
351  *         NULL if we can not even queue the request (insufficient
352  *         memory); if NULL is returned, "notify" will NOT be called.
353  */
354 struct GNUNET_MESH_TransmitHandle *
355 GNUNET_MESH_notify_transmit_ready (struct GNUNET_MESH_Tunnel *tunnel,
356                                    int cork,
357                                    uint32_t priority,
358                                    struct GNUNET_TIME_Relative maxdelay,
359                                    const struct GNUNET_PeerIdentity *target,
360                                    size_t notify_size,
361                                    GNUNET_CONNECTION_TransmitReadyNotify
362                                    notify,
363                                    void *notify_cls) {
364     struct GNUNET_MESH_TransmitHandle   *handle;
365
366     handle = GNUNET_malloc(sizeof(struct GNUNET_MESH_TransmitHandle));
367
368     return handle;
369 }
370
371
372 #if 0                           /* keep Emacsens' auto-indent happy */
373 {
374 #endif
375 #ifdef __cplusplus
376 }
377 #endif