aboutsummaryrefslogtreecommitdiff
path: root/src/conversation
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2013-10-03 13:50:35 +0000
committerChristian Grothoff <christian@grothoff.org>2013-10-03 13:50:35 +0000
commit653dc47fa8ab2e2f36c4ca494fcb6510cdc9d46a (patch)
tree2f2dca0370c0713e508fe188eedae1efb8d65671 /src/conversation
parent4954b2047093f62c866d145ece0d2304b76a428f (diff)
downloadgnunet-653dc47fa8ab2e2f36c4ca494fcb6510cdc9d46a.tar.gz
gnunet-653dc47fa8ab2e2f36c4ca494fcb6510cdc9d46a.zip
-finishing first round of conversation phone API implementation
Diffstat (limited to 'src/conversation')
-rw-r--r--src/conversation/Makefile.am1
-rw-r--r--src/conversation/conversation.h29
-rw-r--r--src/conversation/conversation_api2.c487
3 files changed, 506 insertions, 11 deletions
diff --git a/src/conversation/Makefile.am b/src/conversation/Makefile.am
index 913acf9af..a91e6a40c 100644
--- a/src/conversation/Makefile.am
+++ b/src/conversation/Makefile.am
@@ -48,6 +48,7 @@ libgnunetconversation_la_LIBADD = \
48 libgnunetspeaker.la \ 48 libgnunetspeaker.la \
49 $(top_builddir)/src/gns/libgnunetgns.la \ 49 $(top_builddir)/src/gns/libgnunetgns.la \
50 $(top_builddir)/src/namestore/libgnunetnamestore.la \ 50 $(top_builddir)/src/namestore/libgnunetnamestore.la \
51 $(top_builddir)/src/identity/libgnunetidentity.la \
51 $(top_builddir)/src/util/libgnunetutil.la 52 $(top_builddir)/src/util/libgnunetutil.la
52 53
53libgnunetconversation_la_LDFLAGS = \ 54libgnunetconversation_la_LDFLAGS = \
diff --git a/src/conversation/conversation.h b/src/conversation/conversation.h
index 73052dfcf..ff4795ef8 100644
--- a/src/conversation/conversation.h
+++ b/src/conversation/conversation.h
@@ -444,6 +444,19 @@ struct ClientPhoneRingMessage
444 444
445 445
446/** 446/**
447 * Service -> Client message for phone is busy.
448 */
449struct ClientPhoneBusyMessage
450{
451 /**
452 * Type is: #GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_BUSY
453 */
454 struct GNUNET_MessageHeader header;
455
456};
457
458
459/**
447 * Client -> Service pick up phone that is ringing. 460 * Client -> Service pick up phone that is ringing.
448 */ 461 */
449struct ClientPhonePickupMessage 462struct ClientPhonePickupMessage
@@ -459,7 +472,7 @@ struct ClientPhonePickupMessage
459 472
460 473
461/** 474/**
462 * Client -> Service hang up phone that may or may not be ringing. 475 * Client <-> Service hang up phone that may or may not be ringing.
463 * Also sent in response to a (failed) `struct ClientCallMessage`. 476 * Also sent in response to a (failed) `struct ClientCallMessage`.
464 */ 477 */
465struct ClientPhoneHangupMessage 478struct ClientPhoneHangupMessage
@@ -609,6 +622,20 @@ struct MeshPhonePickupMessage
609 622
610 623
611/** 624/**
625 * Mesh message for phone busy.
626 */
627struct MeshPhoneBusyMessage
628{
629 /**
630 * Type is: #GNUNET_MESSAGE_TYPE_CONVERSATION_MESH_PHONE_BUSY
631 */
632 struct GNUNET_MessageHeader header;
633
634 /* followed by variable-size 0-terminated metadata string??? */
635};
636
637
638/**
612 * Mesh message to transmit the audio. 639 * Mesh message to transmit the audio.
613 */ 640 */
614struct MeshAudioMessage 641struct MeshAudioMessage
diff --git a/src/conversation/conversation_api2.c b/src/conversation/conversation_api2.c
index 3c19828a4..236bd5734 100644
--- a/src/conversation/conversation_api2.c
+++ b/src/conversation/conversation_api2.c
@@ -27,6 +27,8 @@
27 */ 27 */
28#include "platform.h" 28#include "platform.h"
29#include "gnunet_conversation_service.h" 29#include "gnunet_conversation_service.h"
30#include "gnunet_gns_service.h"
31#include "conversation.h"
30 32
31 33
32/** 34/**
@@ -52,11 +54,37 @@ struct PhoneRecord
52 /** 54 /**
53 * Identity of the peer hosting the phone service. 55 * Identity of the peer hosting the phone service.
54 */ 56 */
55 struct GNUNET_PeerIdentity my_peer; 57 struct GNUNET_PeerIdentity peer;
56 58
57}; 59};
58 60
59 61
62/**
63 * Possible states of the phone.
64 */
65enum PhoneState
66{
67 /**
68 * We still need to register the phone.
69 */
70 PS_REGISTER = 0,
71
72 /**
73 * We are waiting for a call.
74 */
75 PS_WAITING,
76
77 /**
78 * The phone is ringing.
79 */
80 PS_RINGING,
81
82 /**
83 * The phone is in an active conversation.
84 */
85 PS_ACTIVE
86};
87
60 88
61/** 89/**
62 * A phone is a device that can ring to signal an incoming call and 90 * A phone is a device that can ring to signal an incoming call and
@@ -75,6 +103,11 @@ struct GNUNET_CONVERSATION_Phone
75 * Our configuration. 103 * Our configuration.
76 */ 104 */
77 const struct GNUNET_CONFIGURATION_Handle *cfg; 105 const struct GNUNET_CONFIGURATION_Handle *cfg;
106
107 /**
108 * Handle to talk with CONVERSATION service.
109 */
110 struct GNUNET_CLIENT_Connection *client;
78 111
79 /** 112 /**
80 * Function to call for phone events. 113 * Function to call for phone events.
@@ -89,35 +122,340 @@ struct GNUNET_CONVERSATION_Phone
89 /** 122 /**
90 * Speaker, or NULL if none is attached. 123 * Speaker, or NULL if none is attached.
91 */ 124 */
92 struct GNUNET_CONVERSATION_Speaker *speaker; 125 struct GNUNET_SPEAKER_Handle *speaker;
93 126
94 /** 127 /**
95 * Microphone, or NULL if none is attached. 128 * Microphone, or NULL if none is attached.
96 */ 129 */
97 struct GNUNET_CONVERSATION_Microphone *mic; 130 struct GNUNET_MICROPHONE_Handle *mic;
131
132 /**
133 * Connection to NAMESTORE (for reverse lookup).
134 */
135 struct GNUNET_NAMESTORE_Handle *ns;
136
137 /**
138 * Active NAMESTORE lookup (or NULL).
139 */
140 struct GNUNET_NAMESTORE_QueueEntry *qe;
141
142 /**
143 * Handle for transmitting to the CONVERSATION service.
144 */
145 struct GNUNET_MQ_Handle *mq;
98 146
99 /** 147 /**
100 * This phone's record. 148 * This phone's record.
101 */ 149 */
102 struct PhoneRecord my_record; 150 struct PhoneRecord my_record;
151
152 /**
153 * My GNS zone.
154 */
155 struct GNUNET_CRYPTO_EccPrivateKey my_zone;
156
157 /**
158 * Identity of the person calling us (valid while in state #PS_RINGING).
159 */
160 struct GNUNET_CRYPTO_EccPublicSignKey caller_id;
161
162 /**
163 * State machine for the phone.
164 */
165 enum PhoneState state;
103 166
104}; 167};
105 168
106 169
107/** 170/**
171 * The phone got disconnected, reconnect to the service.
172 *
173 * @param phone phone to reconnect
174 */
175static void
176reconnect_phone (struct GNUNET_CONVERSATION_Phone *phone);
177
178
179/**
180 * We have resolved the caller ID using our name service.
181 *
182 * @param cls the `struct GNUNET_CONVERSATION_Phone`
183 * @param zone our zone used for resolution
184 * @param label name of the caller
185 * @param rd_count number of records we have in @a rd
186 * @param rd records we have for the caller's label
187 */
188static void
189handle_caller_name (void *cls,
190 const struct GNUNET_CRYPTO_EccPrivateKey *zone,
191 const char *label,
192 unsigned int rd_count,
193 const struct GNUNET_NAMESTORE_RecordData *rd)
194{
195 struct GNUNET_CONVERSATION_Phone *phone = cls;
196 char *name;
197
198 phone->qe = NULL;
199 if (NULL == label)
200 name = GNUNET_strdup (GNUNET_NAMESTORE_pkey_to_zkey (&phone->caller_id));
201 else
202 GNUNET_asprintf (&name, "%.gnu", label);
203 phone->event_handler (phone->event_handler_cls,
204 GNUNET_CONVERSATION_EC_RING,
205 name);
206 GNUNET_free (name);
207}
208
209
210/**
211 * We received a `struct ClientPhoneRingMessage`
212 *
213 * @param cls the `struct GNUNET_CONVERSATION_Phone`
214 * @param msg the message
215 */
216static void
217handle_phone_ring (void *cls,
218 const struct GNUNET_MessageHeader *msg)
219{
220 struct GNUNET_CONVERSATION_Phone *phone = cls;
221 const struct ClientPhoneRingMessage *ring;
222
223 ring = (const struct ClientPhoneRingMessage *) msg;
224 switch (phone->state)
225 {
226 case PS_REGISTER:
227 GNUNET_assert (0);
228 break;
229 case PS_WAITING:
230 phone->state = PS_RINGING;
231 phone->caller_id = ring->caller_id;
232 phone->qe = GNUNET_NAMESTORE_zone_to_name (phone->ns,
233 &phone->my_zone,
234 &ring->caller_id,
235 &handle_caller_name,
236 phone);
237 break;
238 case PS_RINGING:
239 GNUNET_break (0);
240 reconnect_phone (phone);
241 break;
242 case PS_ACTIVE:
243 GNUNET_break (0);
244 reconnect_phone (phone);
245 break;
246 }
247}
248
249
250/**
251 * We received a `struct ClientPhoneHangupMessage`.
252 *
253 * @param cls the `struct GNUNET_CONVERSATION_Phone`
254 * @param msg the message
255 */
256static void
257handle_phone_hangup (void *cls,
258 const struct GNUNET_MessageHeader *msg)
259{
260 struct GNUNET_CONVERSATION_Phone *phone = cls;
261 const struct ClientPhoneHangupMessage *hang;
262 size_t len;
263 const char *reason;
264
265 hang = (const struct ClientPhoneHangupMessage *) msg;
266 reason = (const char *) &hang[1];
267 len = htons (hang->header.size) - sizeof (struct ClientPhoneHangupMessage);
268 if ( (0 == len) ||
269 ('\0' != reason[len-1]) )
270 {
271 GNUNET_break (0);
272 reconnect_phone (phone);
273 return;
274 }
275 switch (phone->state)
276 {
277 case PS_REGISTER:
278 GNUNET_assert (0);
279 break;
280 case PS_WAITING:
281 GNUNET_break (0);
282 reconnect_phone (phone);
283 break;
284 case PS_RINGING:
285 if (NULL != phone->qe)
286 {
287 GNUNET_NAMESTORE_cancel (phone->qe);
288 phone->qe = NULL;
289 phone->state = PS_WAITING;
290 break;
291 }
292 phone->state = PS_WAITING;
293 phone->event_handler (phone->event_handler_cls,
294 GNUNET_CONVERSATION_EC_TERMINATED,
295 reason);
296 break;
297 case PS_ACTIVE:
298 GNUNET_break (NULL == phone->qe);
299 phone->state = PS_WAITING;
300 phone->event_handler (phone->event_handler_cls,
301 GNUNET_CONVERSATION_EC_TERMINATED,
302 reason);
303 break;
304 }
305}
306
307
308/**
309 * We received a `struct ClientAudioMessage`
310 *
311 * @param cls the `struct GNUNET_CONVERSATION_Phone`
312 * @param msg the message
313 */
314static void
315handle_audio_message (void *cls,
316 const struct GNUNET_MessageHeader *msg)
317{
318 struct GNUNET_CONVERSATION_Phone *phone = cls;
319 const struct ClientAudioMessage *am;
320
321 am = (const struct ClientAudioMessage *) msg;
322 switch (phone->state)
323 {
324 case PS_REGISTER:
325 GNUNET_assert (0);
326 break;
327 case PS_WAITING:
328 GNUNET_break (0);
329 reconnect_phone (phone);
330 break;
331 case PS_RINGING:
332 GNUNET_break (0);
333 reconnect_phone (phone);
334 break;
335 case PS_ACTIVE:
336 phone->speaker->play (phone->speaker->cls,
337 ntohs (msg->size) - sizeof (struct ClientAudioMessage),
338 &am[1]);
339 break;
340 }
341}
342
343
344/**
345 * We encountered an error talking with the conversation service.
346 *
347 * @param cls the `struct GNUNET_CONVERSATION_Phone`
348 * @param error details about the error
349 */
350static void
351error_handler (void *cls,
352 enum GNUNET_MQ_Error error)
353{
354 struct GNUNET_CONVERSATION_Phone *phone = cls;
355
356 GNUNET_break (0);
357 reconnect_phone (phone);
358}
359
360
361/**
362 * The phone got disconnected, reconnect to the service.
363 *
364 * @param phone phone to reconnect
365 */
366static void
367reconnect_phone (struct GNUNET_CONVERSATION_Phone *phone)
368{
369 static struct GNUNET_MQ_MessageHandler handlers[] =
370 {
371 { &handle_phone_ring,
372 GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_RING,
373 sizeof (struct ClientPhoneRingMessage) },
374 { &handle_phone_hangup,
375 GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_HANG_UP,
376 0 },
377 { &handle_audio_message,
378 GNUNET_MESSAGE_TYPE_CONVERSATION_CS_AUDIO,
379 0 },
380 { NULL, 0, 0 }
381 };
382 struct GNUNET_MQ_Envelope *e;
383 struct ClientPhoneRegisterMessage *reg;
384
385 if (NULL != phone->mq)
386 {
387 GNUNET_MQ_destroy (phone->mq);
388 phone->mq = NULL;
389 }
390 if (NULL != phone->client)
391 {
392 GNUNET_CLIENT_disconnect (phone->client);
393 phone->client = NULL;
394 }
395 phone->state = PS_REGISTER;
396 phone->client = GNUNET_CLIENT_connect ("conversation", phone->cfg);
397 if (NULL == phone->client)
398 return;
399 phone->mq = GNUNET_MQ_queue_for_connection_client (phone->client,
400 handlers,
401 &error_handler,
402 phone);
403 e = GNUNET_MQ_msg (reg, GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_REGISTER);
404 reg->line = phone->my_record.line;
405 GNUNET_MQ_send (phone->mq, e);
406 phone->state = PS_WAITING;
407}
408
409
410/**
108 * Create a new phone. 411 * Create a new phone.
109 * 412 *
110 * @param cfg configuration for the phone; specifies the phone service and 413 * @param cfg configuration for the phone; specifies the phone service and
111 * which line the phone is to be connected to 414 * which line the phone is to be connected to
415 * @param ego ego to use for name resolution (when determining caller ID)
112 * @param event_handler how to notify the owner of the phone about events 416 * @param event_handler how to notify the owner of the phone about events
113 * @param event_handler_cls closure for @a event_handler 417 * @param event_handler_cls closure for @a event_handler
114 */ 418 */
115struct GNUNET_CONVERSATION_Phone * 419struct GNUNET_CONVERSATION_Phone *
116GNUNET_CONVERSATION_phone_create (const struct GNUNET_CONFIGURATION_Handle *cfg, 420GNUNET_CONVERSATION_phone_create (const struct GNUNET_CONFIGURATION_Handle *cfg,
117 GNUNET_CONVERSATION_EventHandler event_handler, 421 const struct GNUNET_IDENTITY_Ego *ego,
422 GNUNET_CONVERSATION_EventHandler event_handler,
118 void *event_handler_cls) 423 void *event_handler_cls)
119{ 424{
120 return NULL; 425 struct GNUNET_CONVERSATION_Phone *phone;
426 unsigned long long line;
427
428 if (GNUNET_OK !=
429 GNUNET_CONFIGURATION_get_value_number (cfg,
430 "CONVERSATION",
431 "LINE",
432 &line))
433 return NULL;
434 phone = GNUNET_new (struct GNUNET_CONVERSATION_Phone);
435 if (GNUNET_OK !=
436 GNUNET_CRYPTO_get_host_identity (cfg,
437 &phone->my_record.peer))
438 {
439 GNUNET_break (0);
440 GNUNET_free (phone);
441 return NULL;
442 }
443 phone->cfg = cfg;
444 phone->my_zone = *GNUNET_IDENTITY_ego_get_private_key (ego);
445 phone->event_handler = event_handler;
446 phone->event_handler_cls = event_handler_cls;
447 phone->ns = GNUNET_NAMESTORE_connect (cfg);
448 phone->my_record.line = htonl ((uint32_t) line);
449 phone->my_record.version = htonl (0);
450 reconnect_phone (phone);
451 if ( (NULL == phone->client) ||
452 (NULL == phone->ns) )
453 {
454 GNUNET_break (0);
455 GNUNET_CONVERSATION_phone_destroy (phone);
456 return NULL;
457 }
458 return phone;
121} 459}
122 460
123 461
@@ -133,7 +471,33 @@ void
133GNUNET_CONVERSATION_phone_get_record (struct GNUNET_CONVERSATION_Phone *phone, 471GNUNET_CONVERSATION_phone_get_record (struct GNUNET_CONVERSATION_Phone *phone,
134 struct GNUNET_NAMESTORE_RecordData *rd) 472 struct GNUNET_NAMESTORE_RecordData *rd)
135{ 473{
136 GNUNET_assert (0); 474 rd->data = &phone->my_record;
475 rd->expiration_time = 0;
476 rd->data_size = sizeof (struct PhoneRecord);
477 rd->record_type = GNUNET_NAMESTORE_TYPE_PHONE;
478 rd->flags = GNUNET_NAMESTORE_RF_NONE;
479}
480
481
482/**
483 * Process recorded audio data.
484 *
485 * @param cls closure with the `struct GNUNET_CONVERSATION_Phone`
486 * @param data_size number of bytes in @a data
487 * @param data audio data to play
488 */
489static void
490transmit_audio (void *cls,
491 size_t data_size,
492 const void *data)
493{
494 struct GNUNET_CONVERSATION_Phone *phone = cls;
495 struct GNUNET_MQ_Envelope *e;
496 struct ClientAudioMessage *am;
497
498 GNUNET_assert (PS_ACTIVE == phone->state);
499 e = GNUNET_MQ_msg_extra (am, data_size, GNUNET_MESSAGE_TYPE_CONVERSATION_CS_AUDIO);
500 GNUNET_MQ_send (phone->mq, e);
137} 501}
138 502
139 503
@@ -152,7 +516,22 @@ GNUNET_CONVERSTATION_phone_pick_up (struct GNUNET_CONVERSATION_Phone *phone,
152 struct GNUNET_SPEAKER_Handle *speaker, 516 struct GNUNET_SPEAKER_Handle *speaker,
153 struct GNUNET_MICROPHONE_Handle *mic) 517 struct GNUNET_MICROPHONE_Handle *mic)
154{ 518{
155 GNUNET_assert (0); 519 struct GNUNET_MQ_Envelope *e;
520 struct ClientPhonePickupMessage *pick;
521 size_t slen;
522
523 GNUNET_assert (PS_RINGING == phone->state);
524 phone->speaker = speaker;
525 phone->mic = mic;
526 slen = strlen (metadata) + 1;
527 e = GNUNET_MQ_msg_extra (pick, slen, GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_PICK_UP);
528 memcpy (&pick[1], metadata, slen);
529 GNUNET_MQ_send (phone->mq, e);
530 phone->state = PS_ACTIVE;
531 phone->speaker->enable_speaker (phone->speaker->cls);
532 phone->mic->enable_microphone (phone->mic->cls,
533 &transmit_audio,
534 phone);
156} 535}
157 536
158 537
@@ -167,7 +546,21 @@ void
167GNUNET_CONVERSTATION_phone_hang_up (struct GNUNET_CONVERSATION_Phone *phone, 546GNUNET_CONVERSTATION_phone_hang_up (struct GNUNET_CONVERSATION_Phone *phone,
168 const char *reason) 547 const char *reason)
169{ 548{
170 GNUNET_assert (0); 549 struct GNUNET_MQ_Envelope *e;
550 struct ClientPhoneHangupMessage *hang;
551 size_t slen;
552
553 GNUNET_assert ( (PS_RINGING == phone->state) ||
554 (PS_ACTIVE == phone->state) );
555 phone->speaker->disable_speaker (phone->speaker->cls);
556 phone->mic->disable_microphone (phone->mic->cls);
557 phone->speaker = NULL;
558 phone->mic = NULL;
559 slen = strlen (reason) + 1;
560 e = GNUNET_MQ_msg_extra (hang, slen, GNUNET_MESSAGE_TYPE_CONVERSATION_CS_PHONE_HANG_UP);
561 memcpy (&hang[1], reason, slen);
562 GNUNET_MQ_send (phone->mq, e);
563 phone->state = PS_WAITING;
171} 564}
172 565
173 566
@@ -179,30 +572,104 @@ GNUNET_CONVERSTATION_phone_hang_up (struct GNUNET_CONVERSATION_Phone *phone,
179void 572void
180GNUNET_CONVERSATION_phone_destroy (struct GNUNET_CONVERSATION_Phone *phone) 573GNUNET_CONVERSATION_phone_destroy (struct GNUNET_CONVERSATION_Phone *phone)
181{ 574{
182 GNUNET_assert (0); 575 if (NULL != phone->speaker)
576 {
577 phone->speaker->disable_speaker (phone->speaker->cls);
578 phone->speaker = NULL;
579 }
580 if (NULL != phone->mic)
581 {
582 phone->mic->disable_microphone (phone->mic->cls);
583 phone->mic = NULL;
584 }
585 if (NULL != phone->qe)
586 {
587 GNUNET_NAMESTORE_cancel (phone->qe);
588 phone->qe = NULL;
589 }
590 if (NULL != phone->ns)
591 {
592 GNUNET_NAMESTORE_disconnect (phone->ns);
593 phone->ns = NULL;
594 }
595 if (NULL != phone->mq)
596 {
597 GNUNET_MQ_destroy (phone->mq);
598 phone->mq = NULL;
599 }
600 if (NULL != phone->client)
601 {
602 GNUNET_CLIENT_disconnect (phone->client);
603 phone->client = NULL;
604 }
605 GNUNET_free (phone);
183} 606}
184 607
185 608
609/* ******************************* Call API *************************** */
610
611
186/** 612/**
187 * Handle for an outgoing call. 613 * Handle for an outgoing call.
188 */ 614 */
189struct GNUNET_CONVERSATION_Call 615struct GNUNET_CONVERSATION_Call
190{ 616{
191 617
618 /**
619 * Our configuration.
620 */
192 const struct GNUNET_CONFIGURATION_Handle *cfg; 621 const struct GNUNET_CONFIGURATION_Handle *cfg;
193 622
623 /**
624 * Handle to talk with CONVERSATION service.
625 */
626 struct GNUNET_CLIENT_Handle *client;
627
628 /**
629 * Our caller identity.
630 */
194 struct GNUNET_IDENTITY_Ego *caller_id; 631 struct GNUNET_IDENTITY_Ego *caller_id;
195 632
633 /**
634 * Target callee as a GNS address/name.
635 */
196 char *callee; 636 char *callee;
197 637
638 /**
639 * Our speaker.
640 */
198 struct GNUNET_CONVERSATION_Speaker *speaker; 641 struct GNUNET_CONVERSATION_Speaker *speaker;
199 642
643 /**
644 * Our microphone.
645 */
200 struct GNUNET_CONVERSATION_Microphone *mic; 646 struct GNUNET_CONVERSATION_Microphone *mic;
201 647
648 /**
649 * Function to call with events.
650 */
202 GNUNET_CONVERSATION_EventHandler event_handler; 651 GNUNET_CONVERSATION_EventHandler event_handler;
203 652
653 /**
654 * Closure for @e event_handler
655 */
204 void *event_handler_cls; 656 void *event_handler_cls;
205 657
658 /**
659 * Connection to GNS (can be NULL).
660 */
661 struct GNUNET_GNS_Handle *gns;
662
663 /**
664 * Active GNS lookup (or NULL).
665 */
666 struct GNUNET_GNS_LookupRequest *gns_lookup;
667
668 /**
669 * Target phone record, only valid after the lookup is done.
670 */
671 struct PhoneRecord phone_record;
672
206}; 673};
207 674
208 675