diff options
author | Andreas Fuchs <fuchandr@in.tum.de> | 2013-10-01 11:34:38 +0000 |
---|---|---|
committer | Andreas Fuchs <fuchandr@in.tum.de> | 2013-10-01 11:34:38 +0000 |
commit | 70c7532c4d0c684afc4158984f9a37ae7cf05ba3 (patch) | |
tree | 693ef5a8b848db69c6e4b79c2d6f2a583f99db0c /src/conversation/conversation_api.c | |
parent | 408c3426ad378e8eef910ca6fea1144110346b0b (diff) | |
download | gnunet-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.c | 751 |
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 | |||
48 | enum GNUNET_CONVERSATION_CallType | ||
49 | { | ||
50 | CALLER = 0, | ||
51 | CALLEE | ||
52 | }; | ||
53 | |||
54 | /** | ||
55 | * Information about a call | ||
56 | */ | ||
57 | struct 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 | */ | ||
79 | struct 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 | */ | ||
140 | static void | ||
141 | setup_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 | */ | ||
198 | static void | ||
199 | check_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 | */ | ||
219 | static void | ||
220 | check_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 | */ | ||
238 | static void | ||
239 | receive_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 | */ | ||
363 | static size_t | ||
364 | transmit_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 | */ | ||
398 | static size_t | ||
399 | transmit_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 | */ | ||
432 | static size_t | ||
433 | transmit_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 | */ | ||
468 | static size_t | ||
469 | transmit_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 | */ | ||
499 | static void | ||
500 | initiate_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 | */ | ||
521 | static void | ||
522 | accept_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 | */ | ||
536 | static void | ||
537 | reject_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 | */ | ||
551 | static void | ||
552 | terminate_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 | */ | ||
565 | static void | ||
566 | gns_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 | */ | ||
605 | static void | ||
606 | gns_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 | |||
631 | struct GNUNET_CONVERSATION_Handle * | ||
632 | GNUNET_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 | |||
687 | void | ||
688 | GNUNET_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 | |||
699 | void | ||
700 | GNUNET_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 | |||
724 | void | ||
725 | GNUNET_CONVERSATION_hangup (struct GNUNET_CONVERSATION_Handle *h) | ||
726 | { | ||
727 | if (NULL == h || NULL == h->client) | ||
728 | return; | ||
729 | |||
730 | terminate_call (h); | ||
731 | } | ||
732 | |||
733 | void | ||
734 | GNUNET_CONVERSATION_accept (struct GNUNET_CONVERSATION_Handle *h) | ||
735 | { | ||
736 | if (NULL == h || NULL == h->client) | ||
737 | return; | ||
738 | |||
739 | accept_call (h); | ||
740 | } | ||
741 | |||
742 | void | ||
743 | GNUNET_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 */ | ||