aboutsummaryrefslogtreecommitdiff
path: root/src/conversation/conversation_api.c
diff options
context:
space:
mode:
authorAndreas Fuchs <fuchandr@in.tum.de>2013-10-01 11:34:38 +0000
committerAndreas Fuchs <fuchandr@in.tum.de>2013-10-01 11:34:38 +0000
commit70c7532c4d0c684afc4158984f9a37ae7cf05ba3 (patch)
tree693ef5a8b848db69c6e4b79c2d6f2a583f99db0c /src/conversation/conversation_api.c
parent408c3426ad378e8eef910ca6fea1144110346b0b (diff)
downloadgnunet-70c7532c4d0c684afc4158984f9a37ae7cf05ba3.tar.gz
gnunet-70c7532c4d0c684afc4158984f9a37ae7cf05ba3.zip
Initial conversation (experimental) commit
Diffstat (limited to 'src/conversation/conversation_api.c')
-rw-r--r--src/conversation/conversation_api.c751
1 files changed, 751 insertions, 0 deletions
diff --git a/src/conversation/conversation_api.c b/src/conversation/conversation_api.c
new file mode 100644
index 000000000..cf06e541a
--- /dev/null
+++ b/src/conversation/conversation_api.c
@@ -0,0 +1,751 @@
1/*
2 This file is part of GNUnet.
3 (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 2, 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 conversation/conversation_api.c
23 * @brief API for conversation
24 * @author Simon Dieterle
25 * @author Andreas Fuchs
26 * STRUCTURE:
27 * - DATA STRUCTURES
28 * - DECLARATIONS
29 * - AUXILIARY FUNCTIONS
30 * - RECEIVE HANDLERS
31 * - SEND FUNCTIONS
32 * - API CALL DEFINITIONS
33 *
34 */
35
36#include <gnunet/platform.h>
37#include <gnunet/gnunet_util_lib.h>
38#include <gnunet/gnunet_gns_service.h>
39#include "gnunet_protocols_conversation.h"
40#include "gnunet_conversation_service.h"
41
42#define MAX_TRANSMIT_DELAY GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 60)
43
44/******************************************************************************/
45/************************ DATA STRUCTURES ****************************/
46/******************************************************************************/
47
48enum GNUNET_CONVERSATION_CallType
49{
50 CALLER = 0,
51 CALLEE
52};
53
54/**
55* Information about a call
56*/
57struct GNUNET_CONVERSATION_CallInformation
58{
59
60 /**
61 * Peer interacting with
62 */
63 struct GNUNET_PeerIdentity peer;
64
65 /**
66 * Type of call (incoming or outgoing)
67 */
68 int type;
69
70 /**
71 * Shows if the call ist fully established
72 */
73 int established;
74};
75
76/**
77 * Opaque handle to the service.
78 */
79struct GNUNET_CONVERSATION_Handle
80{
81
82 /**
83 * Our configuration.
84 */
85 const struct GNUNET_CONFIGURATION_Handle *cfg;
86
87 /**
88 * Handle to the server connection, to send messages later
89 */
90 struct GNUNET_CLIENT_Connection *client;
91
92 /**
93 * GNS handle
94 */
95 struct GNUNET_GNS_Handle *gns;
96
97 /**
98 * Namestore handle
99 */
100 struct GNUNET_NAMESTORE_Handle *namestore;
101
102 /**
103 * TXT record for gns
104 */
105 int txt_record_set;
106
107 /**
108 * Callback for incoming calls
109 */
110 GNUNET_CONVERSATION_CallHandler *call_handler;
111
112 /**
113 * Callback for rejected calls
114 */
115 GNUNET_CONVERSATION_RejectHandler *reject_handler;
116
117 /**
118 * Callback for notifications
119 */
120 GNUNET_CONVERSATION_NotificationHandler *notification_handler;
121
122 /**
123 * Callback for missed calls
124 */
125 GNUNET_CONVERSATION_MissedCallHandler *missed_call_handler;
126
127 /**
128 * The pointer to the call
129 */
130 struct GNUNET_CONVERSATION_CallInformation *call;
131};
132
133/******************************************************************************/
134/*********************** AUXILIARY FUNCTIONS *************************/
135/******************************************************************************/
136
137/**
138* Initialize the conversation txt record in GNS
139*/
140static void
141setup_gns_txt (struct GNUNET_CONVERSATION_Handle *handle)
142{
143 struct GNUNET_CRYPTO_EccPublicKey zone_pkey;
144 struct GNUNET_CRYPTO_EccPrivateKey *zone_key;
145 struct GNUNET_CRYPTO_EccPublicKey peer_pkey;
146 struct GNUNET_CRYPTO_EccPrivateKey *peer_key;
147 struct GNUNET_NAMESTORE_RecordData rd;
148 struct GNUNET_HashCode hash;
149 struct GNUNET_PeerIdentity peer;
150
151 char *zone_keyfile;
152 char *peer_keyfile;
153
154 rd.expiration_time = UINT64_MAX;
155
156 if (GNUNET_OK !=
157 GNUNET_CONFIGURATION_get_value_filename (handle->cfg, "gns", "ZONEKEY",
158 &zone_keyfile))
159 {
160 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to get key from cfg\n");
161 return;
162 }
163
164 if (GNUNET_OK !=
165 GNUNET_CONFIGURATION_get_value_filename (handle->cfg, "PEER",
166 "PRIVATE_KEY", &peer_keyfile))
167 {
168 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to get key from cfg\n");
169 return;
170 }
171
172 zone_key = GNUNET_CRYPTO_ecc_key_create_from_file (zone_keyfile);
173 GNUNET_CRYPTO_ecc_key_get_public (zone_key, &zone_pkey);
174 peer_key = GNUNET_CRYPTO_ecc_key_create_from_file (peer_keyfile);
175 GNUNET_CRYPTO_ecc_key_get_public (peer_key, &peer_pkey);
176
177 GNUNET_CRYPTO_hash (&peer_pkey, sizeof (peer_pkey), &hash);
178
179 peer.hashPubKey = hash;
180 const char *h = GNUNET_i2s_full (&peer);
181
182 rd.data_size = strlen (h) + 1;
183 rd.data = h;
184 rd.record_type = GNUNET_GNS_RECORD_TXT;
185 rd.flags = GNUNET_NAMESTORE_RF_AUTHORITY;
186
187 GNUNET_NAMESTORE_record_put_by_authority (handle->namestore, zone_key,
188 "conversation", 1, &rd, NULL, NULL);
189}
190
191/**
192* Callback for checking the conversation txt gns record
193*
194* @param cls closure
195* @param rd_count
196* @param rd
197*/
198static void
199check_gns_cb (void *cls, uint32_t rd_count,
200 const struct GNUNET_NAMESTORE_RecordData *rd)
201{
202 struct GNUNET_CONVERSATION_Handle *h = (struct GNUNET_CONVERSATION_Handle *) cls;
203
204 if (0 == rd_count)
205 {
206 setup_gns_txt (h);
207 }
208 else
209 {
210 h->txt_record_set = GNUNET_YES;
211 }
212
213 return;
214}
215
216/**
217* Check if the gns txt record for conversation exits
218*/
219static void
220check_gns (struct GNUNET_CONVERSATION_Handle *h)
221{
222 GNUNET_GNS_lookup (h->gns, "conversation.gads", GNUNET_GNS_RECORD_TXT,
223 GNUNET_NO, NULL, &check_gns_cb, (void *) h);
224
225 return;
226}
227
228/******************************************************************************/
229/*********************** RECEIVE HANDLERS ****************************/
230/******************************************************************************/
231
232/**
233 * Function to process all messages received from the service
234 *
235 * @param cls closure
236 * @param msg message received, NULL on timeout or fatal error
237 */
238static void
239receive_message_cb (void *cls, const struct GNUNET_MessageHeader *msg)
240{
241 struct ServerClientAvailableAnswerMessage *avbmsg;
242 struct ServerClientSessionInitiateMessage *imsg;
243 struct ServerClientSessionRejectMessage *rmsg;
244 struct GNUNET_CONVERSATION_MissedCallNotification *missed_calls;
245 struct GNUNET_CONVERSATION_Handle *h = (struct GNUNET_CONVERSATION_Handle *) cls;
246
247 if (NULL != msg)
248 {
249 switch (ntohs (msg->type))
250 {
251 case GNUNET_MESSAGE_TYPE_CONVERSATION_SC_SESSION_ACCEPT:
252 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
253 _("%s has accepted your call.\n"),
254 GNUNET_i2s_full (&(h->call->peer)));
255
256 h->notification_handler (NULL, h, NotificationType_CALL_ACCEPTED,
257 &(h->call->peer));
258 h->call->type = CALLEE;
259
260 break;
261
262 case GNUNET_MESSAGE_TYPE_CONVERSATION_SC_SESSION_REJECT:
263 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
264 _("%s has rejected your call.\n"),
265 GNUNET_i2s_full (&(h->call->peer)));
266
267 rmsg = (struct ServerClientSessionRejectMessage *) msg;
268 h->reject_handler (NULL, h, ntohs (rmsg->reason), &(h->call->peer));
269 GNUNET_free (h->call);
270 h->call = NULL;
271
272 break;
273
274 case GNUNET_MESSAGE_TYPE_CONVERSATION_SC_SESSION_TERMINATE:
275 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
276 _("%s has terminated the call.\n"),
277 GNUNET_i2s_full (&(h->call->peer)));
278
279 h->notification_handler (NULL, h, NotificationType_CALL_TERMINATED,
280 &(h->call->peer));
281 GNUNET_free (h->call);
282 h->call = NULL;
283
284 break;
285
286 case GNUNET_MESSAGE_TYPE_CONVERSATION_SC_SESSION_INITIATE:
287 imsg = (struct ServerClientSessionInitiateMessage *) msg;
288
289 GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("%s wants to call you.\n"),
290 GNUNET_i2s_full (&(imsg->peer)));
291
292 h->call =
293 (struct GNUNET_CONVERSATION_CallInformation *)
294 GNUNET_malloc (sizeof (struct GNUNET_CONVERSATION_CallInformation));
295 memcpy (&(h->call->peer), &(imsg->peer),
296 sizeof (struct GNUNET_PeerIdentity));
297 h->call_handler (NULL, h, &(h->call->peer));
298 h->call->type = CALLEE;
299
300 break;
301
302 case GNUNET_MESSAGE_TYPE_CONVERSATION_SC_MISSED_CALL:
303 missed_calls =
304 (struct GNUNET_CONVERSATION_MissedCallNotification *) (msg +
305 (sizeof
306 (struct
307 GNUNET_MessageHeader)));
308 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
309 _("You &d have missed a calls.\n"),
310 missed_calls->number);
311 h->missed_call_handler (NULL, h, missed_calls);
312 break;
313
314 case GNUNET_MESSAGE_TYPE_CONVERSATION_SC_SERVICE_BLOCKED:
315 GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("The service is blocked.\n"));
316 h->notification_handler (NULL, h, NotificationType_SERVICE_BLOCKED,
317 NULL);
318 break;
319
320 case GNUNET_MESSAGE_TYPE_CONVERSATION_SC_PEER_NOT_CONNECTED:
321 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
322 _("The peer you are calling is not connected.\n"));
323 h->notification_handler (NULL, h, NotificationType_NO_PEER, NULL);
324 break;
325
326 case GNUNET_MESSAGE_TYPE_CONVERSATION_SC_NO_ANSWER:
327 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
328 _("The peer you are calling does not answer.\n"));
329 h->notification_handler (NULL, h, NotificationType_NO_ANSWER,
330 &(h->call->peer));
331 break;
332
333 case GNUNET_MESSAGE_TYPE_CONVERSATION_SC_ERROR:
334 GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Generic error occured.\n"));
335 break;
336
337 default:
338 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
339 _("Got unknown message type.\n"));
340 break;
341 }
342
343 }
344
345 GNUNET_CLIENT_receive (h->client, &receive_message_cb, h,
346 GNUNET_TIME_UNIT_FOREVER_REL);
347}
348
349/******************************************************************************/
350/************************ SEND FUNCTIONS ****************************/
351/******************************************************************************/
352
353/**
354 * Function called to send a session initiate message to the service.
355 * "buf" will be NULL and "size" zero if the socket was closed for writing in
356 * the meantime.
357 *
358 * @param cls closure, NULL
359 * @param size number of bytes available in buf
360 * @param buf where the callee should write the initiate message
361 * @return number of bytes written to buf
362 */
363static size_t
364transmit_session_initiate_message (void *cls, size_t size, void *buf)
365{
366 size_t msg_size;
367 struct ClientServerSessionInitiateMessage *msg;
368 struct GNUNET_CONVERSATION_Handle *h = (struct GNUNET_CONVERSATION_Handle *) cls;
369
370 msg_size = sizeof (struct ClientServerSessionInitiateMessage);
371
372 GNUNET_assert (size >= msg_size);
373 msg = buf;
374 msg->header.size = htons (msg_size);
375 msg->header.type = htons (GNUNET_MESSAGE_TYPE_CONVERSATION_CS_SESSION_INITIATE);
376 memcpy (&msg->peer, &(h->call->peer), sizeof (struct GNUNET_PeerIdentity));
377
378 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
379 _
380 ("Sending ClientServerSessionInitiateMessage to the service for peer: %s\n"),
381 GNUNET_i2s_full (&(h->call->peer)));
382
383 h->call->type = CALLER;
384
385 return msg_size;
386}
387
388/**
389 * Function called to send a session accept message to the service.
390 * "buf" will be NULL and "size" zero if the socket was closed for writing in
391 * the meantime.
392 *
393 * @param cls closure, NULL
394 * @param size number of bytes available in buf
395 * @param buf where the callee should write the accept message
396 * @return number of bytes written to buf
397 */
398static size_t
399transmit_session_accept_message (void *cls, size_t size, void *buf)
400{
401 size_t msg_size;
402 struct ClientServerSessionAcceptMessage *msg;
403 struct GNUNET_CONVERSATION_Handle *h = (struct GNUNET_CONVERSATION_Handle *) cls;
404
405 msg_size = sizeof (struct ClientServerSessionAcceptMessage);
406
407 GNUNET_assert (size >= msg_size);
408 msg = buf;
409 msg->header.size = htons (msg_size);
410 msg->header.type = htons (GNUNET_MESSAGE_TYPE_CONVERSATION_CS_SESSION_ACCEPT);
411
412 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
413 _
414 ("Sending ClienServerSessionAcceptMessage to the service for peer: %s\n"),
415 GNUNET_i2s_full (&(h->call->peer)));
416
417 h->call->established = GNUNET_YES;
418
419 return msg_size;
420}
421
422/**
423 * Function called to send a session reject message to the service.
424 * "buf" will be NULL and "size" zero if the socket was closed for writing in
425 * the meantime.
426 *
427 * @param cls closure, NULL
428 * @param size number of bytes available in buf
429 * @param buf where the callee should write the reject message
430 * @return number of bytes written to buf
431 */
432static size_t
433transmit_session_reject_message (void *cls, size_t size, void *buf)
434{
435 size_t msg_size;
436 struct ClientServerSessionRejectMessage *msg;
437 struct GNUNET_CONVERSATION_Handle *h = (struct GNUNET_CONVERSATION_Handle *) cls;
438
439 msg_size = sizeof (struct ClientServerSessionRejectMessage);
440
441 GNUNET_assert (size >= msg_size);
442 msg = buf;
443 msg->header.size = htons (msg_size);
444 msg->header.type = htons (GNUNET_MESSAGE_TYPE_CONVERSATION_CS_SESSION_REJECT);
445 msg->reason = htons (REJECT_REASON_NOT_WANTED);
446
447 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
448 _
449 ("Sending ClientServerSessionRejectMessage to the service for peer: %s\n"),
450 GNUNET_i2s_full (&(h->call->peer)));
451
452 GNUNET_free (h->call);
453 h->call = NULL;
454
455 return msg_size;
456}
457
458/**
459 * Function called to send a session terminate message to the service.
460 * "buf" will be NULL and "size" zero if the socket was closed for writing in
461 * the meantime.
462 *
463 * @param cls closure, NULL
464 * @param size number of bytes available in buf
465 * @param buf where the callee should write the terminate message
466 * @return number of bytes written to buf
467 */
468static size_t
469transmit_session_terminate_message (void *cls, size_t size, void *buf)
470{
471 size_t msg_size;
472 struct ClientServerSessionTerminateMessage *msg;
473 struct GNUNET_CONVERSATION_Handle *h = (struct GNUNET_CONVERSATION_Handle *) cls;
474
475 msg_size = sizeof (struct ClientServerSessionTerminateMessage);
476
477 GNUNET_assert (size >= msg_size);
478 msg = buf;
479 msg->header.size = htons (msg_size);
480 msg->header.type = htons (GNUNET_MESSAGE_TYPE_CONVERSATION_CS_SESSION_TERMINATE);
481
482 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
483 _
484 ("Sending ClientServerSessionTerminateMessage to the service for peer: %s\n"),
485 GNUNET_i2s_full (&(h->call->peer)));
486
487 GNUNET_free (h->call);
488 h->call = NULL;
489
490 return msg_size;
491}
492
493/**
494 * Auxiliary function to call a peer.
495 *
496 * @param h conversation handle
497 * @return
498 */
499static void
500initiate_call (struct GNUNET_CONVERSATION_Handle *h, struct GNUNET_PeerIdentity peer)
501{
502 h->call =
503 (struct GNUNET_CONVERSATION_CallInformation *)
504 GNUNET_malloc (sizeof (struct GNUNET_CONVERSATION_CallInformation));
505 memcpy (&(h->call->peer), &peer, sizeof (struct GNUNET_PeerIdentity));
506
507 GNUNET_CLIENT_notify_transmit_ready (h->client,
508 sizeof (struct
509 ClientServerSessionInitiateMessage),
510 MAX_TRANSMIT_DELAY, GNUNET_YES,
511 &transmit_session_initiate_message, h);
512
513 return;
514}
515
516/**
517 * Auxiliary function to accept a call.
518 *
519 * @param h conversation handle
520 */
521static void
522accept_call (struct GNUNET_CONVERSATION_Handle *h)
523{
524 GNUNET_CLIENT_notify_transmit_ready (h->client,
525 sizeof (struct
526 ClientServerSessionAcceptMessage),
527 MAX_TRANSMIT_DELAY, GNUNET_YES,
528 &transmit_session_accept_message, h);
529}
530
531/**
532 * Auxiliary function to reject a call.
533 *
534 * @param h conversation handle
535 */
536static void
537reject_call (struct GNUNET_CONVERSATION_Handle *h)
538{
539 GNUNET_CLIENT_notify_transmit_ready (h->client,
540 sizeof (struct
541 ClientServerSessionRejectMessage),
542 MAX_TRANSMIT_DELAY, GNUNET_YES,
543 &transmit_session_reject_message, h);
544}
545
546/**
547 * Auxiliary function to terminate a call.
548 *
549 * @param h conversation handle
550 */
551static void
552terminate_call (struct GNUNET_CONVERSATION_Handle *h)
553{
554 GNUNET_CLIENT_notify_transmit_ready (h->client,
555 sizeof (struct
556 ClientServerSessionTerminateMessage),
557 MAX_TRANSMIT_DELAY, GNUNET_YES,
558 &transmit_session_terminate_message,
559 h);
560}
561
562/**
563*
564*/
565static void
566gns_call_cb (void *cls, uint32_t rd_count,
567 const struct GNUNET_NAMESTORE_RecordData *rd)
568{
569 struct GNUNET_PeerIdentity peer;
570 char hash[104];
571 struct GNUNET_CONVERSATION_Handle *handle = (struct GNUNET_CONVERSATION_Handle *) cls;
572 int i = 0;
573
574 if (0 == rd_count)
575 {
576 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Lookup failed\n");
577 handle->notification_handler (NULL, handle, NotificationType_NO_PEER,
578 NULL);
579 }
580 else
581 {
582 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Lookup succeeded\n");
583
584 if (GNUNET_GNS_RECORD_TXT == rd[i].record_type)
585 {
586 memcpy (&hash, rd[i].data, 104);
587 GNUNET_CRYPTO_hash_from_string2 (hash, strlen (hash),
588 &(peer.hashPubKey));
589
590 initiate_call (handle, peer);
591 }
592 else
593 {
594 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No resolution!\n");
595 handle->notification_handler (NULL, handle,
596 NotificationType_NO_PEER, NULL);
597 }
598 }
599 return;
600}
601
602/**
603* GNS lookup
604*/
605static void
606gns_lookup_and_call (struct GNUNET_CONVERSATION_Handle *h, const char *callee)
607{
608 char domain[GNUNET_DNSPARSER_MAX_NAME_LENGTH];
609 char *pos;
610
611 pos = domain;
612 strcpy (pos, "conversation");
613 pos += strlen ("conversation");
614 strcpy (pos, ".");
615 pos++;
616 strcpy (pos, callee);
617 pos += strlen (callee);
618
619 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Lookup for %s\n", domain);
620
621 GNUNET_GNS_lookup (h->gns, domain, GNUNET_GNS_RECORD_TXT, GNUNET_NO, NULL,
622 &gns_call_cb, h);
623
624 return;
625}
626
627/******************************************************************************/
628/********************** API CALL DEFINITIONS *************************/
629/******************************************************************************/
630
631struct GNUNET_CONVERSATION_Handle *
632GNUNET_CONVERSATION_connect (const struct GNUNET_CONFIGURATION_Handle *cfg, void *cls,
633 GNUNET_CONVERSATION_CallHandler * call_handler,
634 GNUNET_CONVERSATION_RejectHandler * reject_handler,
635 GNUNET_CONVERSATION_NotificationHandler * notification_handler,
636 GNUNET_CONVERSATION_MissedCallHandler * missed_call_handler)
637{
638 struct GNUNET_CONVERSATION_Handle *h;
639
640 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "GNUNET_CONVERSATION_connect()\n");
641 h = GNUNET_malloc (sizeof (struct GNUNET_CONVERSATION_Handle));
642
643 h->cfg = cfg;
644 h->call_handler = call_handler;
645 h->reject_handler = reject_handler;
646 h->notification_handler = notification_handler;
647 h->missed_call_handler = missed_call_handler;
648
649 if (NULL == (h->client = GNUNET_CLIENT_connect ("conversation", cfg)))
650 {
651 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Could not access CONVERSATION service\n");
652 GNUNET_break (0);
653 GNUNET_free (h);
654
655 return NULL;
656 }
657
658 if (NULL == (h->gns = GNUNET_GNS_connect (cfg)))
659 {
660 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Could not access GNS service\n");
661 GNUNET_break (0);
662 GNUNET_CLIENT_disconnect (h->client);
663 GNUNET_free (h);
664
665 return NULL;
666 }
667
668 if (NULL == (h->namestore = GNUNET_NAMESTORE_connect (cfg)))
669 {
670 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
671 "Could not access NAMESTORE service\n");
672 GNUNET_break (0);
673 GNUNET_CLIENT_disconnect (h->client);
674 GNUNET_GNS_disconnect (h->gns);
675 GNUNET_free (h);
676
677 return NULL;
678 }
679
680 check_gns (h);
681 GNUNET_CLIENT_receive (h->client, &receive_message_cb, h,
682 GNUNET_TIME_UNIT_FOREVER_REL);
683
684 return h;
685}
686
687void
688GNUNET_CONVERSATION_disconnect (struct GNUNET_CONVERSATION_Handle *handle)
689{
690 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "CONVERSATION DISCONNECT\n");
691
692 GNUNET_CLIENT_disconnect (handle->client);
693 GNUNET_GNS_disconnect (handle->gns);
694
695 GNUNET_free (handle);
696 handle = NULL;
697}
698
699void
700GNUNET_CONVERSATION_call (struct GNUNET_CONVERSATION_Handle *h, const char *callee,
701 int doGnsLookup)
702{
703 struct GNUNET_PeerIdentity peer;
704 if (NULL == h || NULL == h->client)
705 return;
706
707 if (GNUNET_YES == doGnsLookup)
708 {
709 gns_lookup_and_call (h, callee);
710 }
711 else
712 {
713 if (GNUNET_OK !=
714 GNUNET_CRYPTO_hash_from_string2 (callee, strlen (callee),
715 &(peer.hashPubKey)))
716 {
717 h->notification_handler (NULL, h, NotificationType_NO_PEER, NULL);
718 }
719
720 initiate_call (h, peer);
721 }
722}
723
724void
725GNUNET_CONVERSATION_hangup (struct GNUNET_CONVERSATION_Handle *h)
726{
727 if (NULL == h || NULL == h->client)
728 return;
729
730 terminate_call (h);
731}
732
733void
734GNUNET_CONVERSATION_accept (struct GNUNET_CONVERSATION_Handle *h)
735{
736 if (NULL == h || NULL == h->client)
737 return;
738
739 accept_call (h);
740}
741
742void
743GNUNET_CONVERSATION_reject (struct GNUNET_CONVERSATION_Handle *h)
744{
745 if (NULL == h || NULL == h->client)
746 return;
747
748 reject_call (h);
749}
750
751/* end of conversation_api.c */