aboutsummaryrefslogtreecommitdiff
path: root/src/transport/transport_api_address_lookup.c
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2012-02-06 21:27:15 +0000
committerChristian Grothoff <christian@grothoff.org>2012-02-06 21:27:15 +0000
commit34228a39153d5ba620f3e8dde666475043af194b (patch)
tree22cdc3a98992c5f5a963be784296e4519dca740a /src/transport/transport_api_address_lookup.c
parentd2b0f1d3b4133ee2b90e820203c05988004d2ff7 (diff)
downloadgnunet-34228a39153d5ba620f3e8dde666475043af194b.tar.gz
gnunet-34228a39153d5ba620f3e8dde666475043af194b.zip
-trying to fix crash from #1972 report
Diffstat (limited to 'src/transport/transport_api_address_lookup.c')
-rw-r--r--src/transport/transport_api_address_lookup.c192
1 files changed, 163 insertions, 29 deletions
diff --git a/src/transport/transport_api_address_lookup.c b/src/transport/transport_api_address_lookup.c
index a21daab5e..32bb41d55 100644
--- a/src/transport/transport_api_address_lookup.c
+++ b/src/transport/transport_api_address_lookup.c
@@ -60,9 +60,34 @@ struct GNUNET_TRANSPORT_PeerIterateContext
60 struct GNUNET_CLIENT_Connection *client; 60 struct GNUNET_CLIENT_Connection *client;
61 61
62 /** 62 /**
63 * Configuration we use.
64 */
65 const struct GNUNET_CONFIGURATION_Handle *cfg;
66
67 /**
63 * When should this operation time out? 68 * When should this operation time out?
64 */ 69 */
65 struct GNUNET_TIME_Absolute timeout; 70 struct GNUNET_TIME_Absolute timeout;
71
72 /**
73 * Backoff for reconnect.
74 */
75 struct GNUNET_TIME_Relative backoff;
76
77 /**
78 * Task ID for reconnect.
79 */
80 GNUNET_SCHEDULER_TaskIdentifier reconnect_task;
81
82 /**
83 * Identity of the peer to monitor.
84 */
85 struct GNUNET_PeerIdentity peer;
86
87 /**
88 * Was this a one-shot request?
89 */
90 int one_shot;
66}; 91};
67 92
68 93
@@ -75,6 +100,81 @@ struct GNUNET_TRANSPORT_PeerIterateContext
75 */ 100 */
76static void 101static void
77peer_address_response_processor (void *cls, 102peer_address_response_processor (void *cls,
103 const struct GNUNET_MessageHeader *msg);
104
105
106/**
107 * Send our subscription request to the service.
108 *
109 * @param pal_ctx our context
110 */
111static void
112send_request (struct GNUNET_TRANSPORT_PeerIterateContext *pal_ctx)
113{
114 struct AddressIterateMessage msg;
115
116 msg.header.size = htons (sizeof (struct AddressIterateMessage));
117 msg.header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_ADDRESS_ITERATE);
118 msg.one_shot = htonl (pal_ctx->one_shot);
119 msg.timeout = GNUNET_TIME_absolute_hton (pal_ctx->timeout);
120 msg.peer = pal_ctx->peer;
121 GNUNET_assert (GNUNET_OK ==
122 GNUNET_CLIENT_transmit_and_get_response (pal_ctx->client,
123 &msg.header,
124 GNUNET_TIME_absolute_get_remaining (pal_ctx->timeout),
125 GNUNET_YES,
126 &peer_address_response_processor,
127 pal_ctx));
128}
129
130/**
131 * Task run to re-establish the connection.
132 *
133 * @param cls our 'struct GNUNET_TRANSPORT_PeerAddressLookupContext*'
134 * @param tc scheduler context, unused
135 */
136static void
137do_connect (void *cls,
138 const struct GNUNET_SCHEDULER_TaskContext *tc)
139{
140 struct GNUNET_TRANSPORT_PeerIterateContext *pal_ctx = cls;
141
142 pal_ctx->reconnect_task = GNUNET_SCHEDULER_NO_TASK;
143 pal_ctx->client = GNUNET_CLIENT_connect ("transport", pal_ctx->cfg);
144 GNUNET_assert (NULL != pal_ctx->client);
145 send_request (pal_ctx);
146}
147
148
149/**
150 * Cut the existing connection and reconnect.
151 *
152 * @param pal_ctx our context
153 */
154static void
155reconnect (struct GNUNET_TRANSPORT_PeerIterateContext *pal_ctx)
156{
157 GNUNET_assert (GNUNET_NO == pal_ctx->one_shot);
158 GNUNET_CLIENT_disconnect (pal_ctx->client, GNUNET_NO);
159 pal_ctx->client = NULL;
160 pal_ctx->backoff = GNUNET_TIME_relative_max (GNUNET_TIME_UNIT_MILLISECONDS,
161 GNUNET_TIME_relative_min (GNUNET_TIME_relative_multiply (pal_ctx->backoff, 2),
162 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 30)));
163 pal_ctx->reconnect_task = GNUNET_SCHEDULER_add_delayed (pal_ctx->backoff,
164 &do_connect,
165 pal_ctx);
166}
167
168
169/**
170 * Function called with responses from the service.
171 *
172 * @param cls our 'struct GNUNET_TRANSPORT_PeerAddressLookupContext*'
173 * @param msg NULL on timeout or error, otherwise presumably a
174 * message with the human-readable address
175 */
176static void
177peer_address_response_processor (void *cls,
78 const struct GNUNET_MessageHeader *msg) 178 const struct GNUNET_MessageHeader *msg)
79{ 179{
80 struct GNUNET_TRANSPORT_PeerIterateContext *pal_ctx = cls; 180 struct GNUNET_TRANSPORT_PeerIterateContext *pal_ctx = cls;
@@ -88,8 +188,15 @@ peer_address_response_processor (void *cls,
88 188
89 if (msg == NULL) 189 if (msg == NULL)
90 { 190 {
91 pal_ctx->cb (pal_ctx->cb_cls, NULL, NULL); 191 if (pal_ctx->one_shot)
92 GNUNET_TRANSPORT_peer_get_active_addresses_cancel (pal_ctx); 192 {
193 pal_ctx->cb (pal_ctx->cb_cls, NULL, NULL);
194 GNUNET_TRANSPORT_peer_get_active_addresses_cancel (pal_ctx);
195 }
196 else
197 {
198 reconnect (pal_ctx);
199 }
93 return; 200 return;
94 } 201 }
95 size = ntohs (msg->size); 202 size = ntohs (msg->size);
@@ -98,8 +205,15 @@ peer_address_response_processor (void *cls,
98 if (size == sizeof (struct GNUNET_MessageHeader)) 205 if (size == sizeof (struct GNUNET_MessageHeader))
99 { 206 {
100 /* done! */ 207 /* done! */
101 pal_ctx->cb (pal_ctx->cb_cls, NULL, NULL); 208 if (pal_ctx->one_shot)
102 GNUNET_TRANSPORT_peer_get_active_addresses_cancel (pal_ctx); 209 {
210 pal_ctx->cb (pal_ctx->cb_cls, NULL, NULL);
211 GNUNET_TRANSPORT_peer_get_active_addresses_cancel (pal_ctx);
212 }
213 else
214 {
215 reconnect (pal_ctx);
216 }
103 return; 217 return;
104 } 218 }
105 219
@@ -108,8 +222,15 @@ peer_address_response_processor (void *cls,
108 GNUNET_MESSAGE_TYPE_TRANSPORT_ADDRESS_ITERATE_RESPONSE)) 222 GNUNET_MESSAGE_TYPE_TRANSPORT_ADDRESS_ITERATE_RESPONSE))
109 { 223 {
110 GNUNET_break (0); 224 GNUNET_break (0);
111 pal_ctx->cb (pal_ctx->cb_cls, NULL, NULL); 225 if (pal_ctx->one_shot)
112 GNUNET_TRANSPORT_peer_get_active_addresses_cancel (pal_ctx); 226 {
227 pal_ctx->cb (pal_ctx->cb_cls, NULL, NULL);
228 GNUNET_TRANSPORT_peer_get_active_addresses_cancel (pal_ctx);
229 }
230 else
231 {
232 reconnect (pal_ctx);
233 }
113 return; 234 return;
114 } 235 }
115 236
@@ -120,8 +241,15 @@ peer_address_response_processor (void *cls,
120 if (size != sizeof (struct AddressIterateResponseMessage) + tlen + alen) 241 if (size != sizeof (struct AddressIterateResponseMessage) + tlen + alen)
121 { 242 {
122 GNUNET_break (0); 243 GNUNET_break (0);
123 pal_ctx->cb (pal_ctx->cb_cls, NULL, NULL); 244 if (pal_ctx->one_shot)
124 GNUNET_TRANSPORT_peer_get_active_addresses_cancel (pal_ctx); 245 {
246 pal_ctx->cb (pal_ctx->cb_cls, NULL, NULL);
247 GNUNET_TRANSPORT_peer_get_active_addresses_cancel (pal_ctx);
248 }
249 else
250 {
251 reconnect (pal_ctx);
252 }
125 return; 253 return;
126 } 254 }
127 255
@@ -136,9 +264,16 @@ peer_address_response_processor (void *cls,
136 264
137 if (transport_name[tlen - 1] != '\0') 265 if (transport_name[tlen - 1] != '\0')
138 { 266 {
139 GNUNET_break_op (0); 267 GNUNET_break (0);
140 pal_ctx->cb (pal_ctx->cb_cls, NULL, NULL); 268 if (pal_ctx->one_shot)
141 GNUNET_TRANSPORT_peer_get_active_addresses_cancel (pal_ctx); 269 {
270 pal_ctx->cb (pal_ctx->cb_cls, NULL, NULL);
271 GNUNET_TRANSPORT_peer_get_active_addresses_cancel (pal_ctx);
272 }
273 else
274 {
275 reconnect (pal_ctx);
276 }
142 return; 277 return;
143 } 278 }
144 279
@@ -185,34 +320,24 @@ GNUNET_TRANSPORT_peer_get_active_addresses (const struct
185 void *peer_address_callback_cls) 320 void *peer_address_callback_cls)
186{ 321{
187 struct GNUNET_TRANSPORT_PeerIterateContext *pal_ctx; 322 struct GNUNET_TRANSPORT_PeerIterateContext *pal_ctx;
188 struct AddressIterateMessage msg;
189 struct GNUNET_CLIENT_Connection *client; 323 struct GNUNET_CLIENT_Connection *client;
190 struct GNUNET_TIME_Absolute abs_timeout;
191 324
192 client = GNUNET_CLIENT_connect ("transport", cfg); 325 client = GNUNET_CLIENT_connect ("transport", cfg);
193 if (client == NULL) 326 if (client == NULL)
194 return NULL; 327 return NULL;
195 if (GNUNET_YES != one_shot) 328 if (GNUNET_YES != one_shot)
196 timeout = GNUNET_TIME_UNIT_FOREVER_REL; 329 timeout = GNUNET_TIME_UNIT_FOREVER_REL;
197 abs_timeout = GNUNET_TIME_relative_to_absolute (timeout);
198 msg.header.size = htons (sizeof (struct AddressIterateMessage));
199 msg.header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_ADDRESS_ITERATE);
200 msg.one_shot = htonl (one_shot);
201 msg.timeout = GNUNET_TIME_absolute_hton (abs_timeout);
202 if (peer == NULL)
203 memset (&msg.peer, 0, sizeof (struct GNUNET_PeerIdentity));
204 else
205 msg.peer = *peer;
206 pal_ctx = GNUNET_malloc (sizeof (struct GNUNET_TRANSPORT_PeerIterateContext)); 330 pal_ctx = GNUNET_malloc (sizeof (struct GNUNET_TRANSPORT_PeerIterateContext));
207 pal_ctx->cb = peer_address_callback; 331 pal_ctx->cb = peer_address_callback;
208 pal_ctx->cb_cls = peer_address_callback_cls; 332 pal_ctx->cb_cls = peer_address_callback_cls;
209 pal_ctx->timeout = abs_timeout; 333 pal_ctx->cfg = cfg;
334 pal_ctx->timeout = GNUNET_TIME_relative_to_absolute (timeout);
335 if (NULL != peer)
336 pal_ctx->peer = *peer;
337 pal_ctx->one_shot = one_shot;
210 pal_ctx->client = client; 338 pal_ctx->client = client;
211 GNUNET_assert (GNUNET_OK == 339 send_request (pal_ctx);
212 GNUNET_CLIENT_transmit_and_get_response (client, &msg.header, 340
213 timeout, GNUNET_YES,
214 &peer_address_response_processor,
215 pal_ctx));
216 return pal_ctx; 341 return pal_ctx;
217} 342}
218 343
@@ -227,7 +352,16 @@ GNUNET_TRANSPORT_peer_get_active_addresses_cancel (struct
227 GNUNET_TRANSPORT_PeerIterateContext 352 GNUNET_TRANSPORT_PeerIterateContext
228 *alc) 353 *alc)
229{ 354{
230 GNUNET_CLIENT_disconnect (alc->client, GNUNET_NO); 355 if (NULL != alc->client)
356 {
357 GNUNET_CLIENT_disconnect (alc->client, GNUNET_NO);
358 alc->client = NULL;
359 }
360 if (GNUNET_SCHEDULER_NO_TASK != alc->reconnect_task)
361 {
362 GNUNET_SCHEDULER_cancel (alc->reconnect_task);
363 alc->reconnect_task = GNUNET_SCHEDULER_NO_TASK;
364 }
231 GNUNET_free (alc); 365 GNUNET_free (alc);
232} 366}
233 367