Merge branch 'master' of ssh://gnunet.org/gnunet
[oweals/gnunet.git] / src / dht / gnunet-service-dht_hello.c
1 /*
2      This file is part of GNUnet.
3      Copyright (C) 2011 GNUnet e.V.
4
5      GNUnet is free software: you can redistribute it and/or modify it
6      under the terms of the GNU Affero General Public License as published
7      by the Free Software Foundation, either version 3 of the License,
8      or (at your 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      Affero General Public License for more details.
14     
15      You should have received a copy of the GNU Affero General Public License
16      along with this program.  If not, see <http://www.gnu.org/licenses/>.
17 */
18
19 /**
20  * @file dht/gnunet-service-dht_hello.c
21  * @brief GNUnet DHT integration with peerinfo
22  * @author Christian Grothoff
23  *
24  * TODO:
25  * - consider adding mechanism to remove expired HELLOs
26  */
27 #include "platform.h"
28 #include "gnunet-service-dht.h"
29 #include "gnunet-service-dht_hello.h"
30 #include "gnunet_peerinfo_service.h"
31
32
33 /**
34  * Handle for peerinfo notifications.
35  */
36 static struct GNUNET_PEERINFO_NotifyContext *pnc;
37
38 /**
39  * Hash map of peers to HELLOs.
40  */
41 static struct GNUNET_CONTAINER_MultiPeerMap *peer_to_hello;
42
43
44 /**
45  * Obtain a peer's HELLO if available
46  *
47  * @param peer peer to look for a HELLO from
48  * @return HELLO for the given peer
49  */
50 const struct GNUNET_HELLO_Message *
51 GDS_HELLO_get (const struct GNUNET_PeerIdentity *peer)
52 {
53   if (NULL == peer_to_hello)
54     return NULL;
55   return GNUNET_CONTAINER_multipeermap_get (peer_to_hello, peer);
56 }
57
58
59 /**
60  * Function called for each HELLO known to PEERINFO.
61  *
62  * @param cls closure
63  * @param peer id of the peer, NULL for last call
64  * @param hello hello message for the peer (can be NULL)
65  * @param err_msg error message (not used)
66  *
67  * FIXME this is called once per address. Merge instead of replacing?
68  */
69 static void
70 process_hello (void *cls,
71                const struct GNUNET_PeerIdentity *peer,
72                const struct GNUNET_HELLO_Message *hello,
73                const char *err_msg)
74 {
75   struct GNUNET_TIME_Absolute ex;
76   struct GNUNET_HELLO_Message *hm;
77
78   if (NULL == hello)
79     return;
80   ex = GNUNET_HELLO_get_last_expiration (hello);
81   if (0 == GNUNET_TIME_absolute_get_remaining (ex).rel_value_us)
82     return;
83   GNUNET_STATISTICS_update (GDS_stats,
84                             gettext_noop ("# HELLOs obtained from peerinfo"), 1,
85                             GNUNET_NO);
86   hm = GNUNET_CONTAINER_multipeermap_get (peer_to_hello, peer);
87   GNUNET_free_non_null (hm);
88   hm = GNUNET_malloc (GNUNET_HELLO_size (hello));
89   GNUNET_memcpy (hm, hello, GNUNET_HELLO_size (hello));
90   GNUNET_assert (GNUNET_SYSERR !=
91                  GNUNET_CONTAINER_multipeermap_put (peer_to_hello,
92                                                     peer, hm,
93                                                     GNUNET_CONTAINER_MULTIHASHMAPOPTION_REPLACE));
94 }
95
96
97 /**
98  * Initialize HELLO subsystem.
99  */
100 void
101 GDS_HELLO_init ()
102 {
103   pnc = GNUNET_PEERINFO_notify (GDS_cfg,
104                                 GNUNET_NO,
105                                 &process_hello,
106                                 NULL);
107   peer_to_hello = GNUNET_CONTAINER_multipeermap_create (256,
108                                                         GNUNET_NO);
109 }
110
111
112 /**
113  * Free memory occopied by the HELLO.
114  */
115 static int
116 free_hello (void *cls,
117             const struct GNUNET_PeerIdentity *key,
118             void *hello)
119 {
120   GNUNET_free (hello);
121   return GNUNET_OK;
122 }
123
124
125 /**
126  * Shutdown HELLO subsystem.
127  */
128 void
129 GDS_HELLO_done ()
130 {
131   if (NULL != pnc)
132   {
133     GNUNET_PEERINFO_notify_cancel (pnc);
134     pnc = NULL;
135   }
136   if (NULL != peer_to_hello)
137   {
138     GNUNET_CONTAINER_multipeermap_iterate (peer_to_hello,
139                                            &free_hello,
140                                            NULL);
141     GNUNET_CONTAINER_multipeermap_destroy (peer_to_hello);
142   }
143 }
144
145 /* end of gnunet-service-dht_hello.c */