00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034 #include "asterisk.h"
00035
00036 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 139283 $")
00037
00038 #include <stdlib.h>
00039 #include <stdio.h>
00040 #include <string.h>
00041 #include <unistd.h>
00042 #include <sys/socket.h>
00043 #include <errno.h>
00044 #include <stdlib.h>
00045 #include <fcntl.h>
00046 #include <netdb.h>
00047 #include <netinet/in.h>
00048 #include <arpa/inet.h>
00049 #include <sys/signal.h>
00050 #include <iksemel.h>
00051 #include <pthread.h>
00052
00053 #ifdef HAVE_GNUTLS
00054 #include <gcrypt.h>
00055 GCRY_THREAD_OPTION_PTHREAD_IMPL;
00056 #endif
00057
00058 #include "asterisk/lock.h"
00059 #include "asterisk/channel.h"
00060 #include "asterisk/config.h"
00061 #include "asterisk/logger.h"
00062 #include "asterisk/module.h"
00063 #include "asterisk/pbx.h"
00064 #include "asterisk/options.h"
00065 #include "asterisk/lock.h"
00066 #include "asterisk/sched.h"
00067 #include "asterisk/io.h"
00068 #include "asterisk/rtp.h"
00069 #include "asterisk/acl.h"
00070 #include "asterisk/callerid.h"
00071 #include "asterisk/file.h"
00072 #include "asterisk/cli.h"
00073 #include "asterisk/app.h"
00074 #include "asterisk/musiconhold.h"
00075 #include "asterisk/manager.h"
00076 #include "asterisk/stringfields.h"
00077 #include "asterisk/utils.h"
00078 #include "asterisk/causes.h"
00079 #include "asterisk/astobj.h"
00080 #include "asterisk/abstract_jb.h"
00081 #include "asterisk/jabber.h"
00082
00083 #define GOOGLE_CONFIG "gtalk.conf"
00084
00085 #define GOOGLE_NS "http://www.google.com/session"
00086
00087
00088
00089 static struct ast_jb_conf default_jbconf =
00090 {
00091 .flags = 0,
00092 .max_size = -1,
00093 .resync_threshold = -1,
00094 .impl = ""
00095 };
00096 static struct ast_jb_conf global_jbconf;
00097
00098 enum gtalk_protocol {
00099 AJI_PROTOCOL_UDP = 1,
00100 AJI_PROTOCOL_SSLTCP = 2,
00101 };
00102
00103 enum gtalk_connect_type {
00104 AJI_CONNECT_STUN = 1,
00105 AJI_CONNECT_LOCAL = 2,
00106 AJI_CONNECT_RELAY = 3,
00107 };
00108
00109 struct gtalk_pvt {
00110 ast_mutex_t lock;
00111 time_t laststun;
00112 struct gtalk *parent;
00113 char sid[100];
00114 char us[AJI_MAX_JIDLEN];
00115 char them[AJI_MAX_JIDLEN];
00116 char ring[10];
00117 iksrule *ringrule;
00118 int initiator;
00119 int alreadygone;
00120 int capability;
00121 struct ast_codec_pref prefs;
00122 struct gtalk_candidate *theircandidates;
00123 struct gtalk_candidate *ourcandidates;
00124 char cid_num[80];
00125 char cid_name[80];
00126 char exten[80];
00127 struct ast_channel *owner;
00128 struct ast_rtp *rtp;
00129 struct ast_rtp *vrtp;
00130 int jointcapability;
00131 int peercapability;
00132 struct gtalk_pvt *next;
00133 };
00134
00135 struct gtalk_candidate {
00136 char name[100];
00137 enum gtalk_protocol protocol;
00138 double preference;
00139 char username[100];
00140 char password[100];
00141 enum gtalk_connect_type type;
00142 char network[6];
00143 int generation;
00144 char ip[16];
00145 int port;
00146 int receipt;
00147 struct gtalk_candidate *next;
00148 };
00149
00150 struct gtalk {
00151 ASTOBJ_COMPONENTS(struct gtalk);
00152 struct aji_client *connection;
00153 struct aji_buddy *buddy;
00154 struct gtalk_pvt *p;
00155 struct ast_codec_pref prefs;
00156 int amaflags;
00157 char user[AJI_MAX_JIDLEN];
00158 char context[AST_MAX_CONTEXT];
00159 char accountcode[AST_MAX_ACCOUNT_CODE];
00160 int capability;
00161 ast_group_t callgroup;
00162 ast_group_t pickupgroup;
00163 int callingpres;
00164 int allowguest;
00165 char language[MAX_LANGUAGE];
00166 char musicclass[MAX_MUSICCLASS];
00167 };
00168
00169 struct gtalk_container {
00170 ASTOBJ_CONTAINER_COMPONENTS(struct gtalk);
00171 };
00172
00173 static const char desc[] = "Gtalk Channel";
00174
00175 static int global_capability = AST_FORMAT_ULAW | AST_FORMAT_ALAW | AST_FORMAT_GSM | AST_FORMAT_H263;
00176
00177 AST_MUTEX_DEFINE_STATIC(gtalklock);
00178
00179
00180 static struct ast_channel *gtalk_request(const char *type, int format, void *data, int *cause);
00181 static int gtalk_digit(struct ast_channel *ast, char digit, unsigned int duration);
00182 static int gtalk_digit_begin(struct ast_channel *ast, char digit);
00183 static int gtalk_digit_end(struct ast_channel *ast, char digit, unsigned int duration);
00184 static int gtalk_call(struct ast_channel *ast, char *dest, int timeout);
00185 static int gtalk_hangup(struct ast_channel *ast);
00186 static int gtalk_answer(struct ast_channel *ast);
00187 static int gtalk_action(struct gtalk *client, struct gtalk_pvt *p, const char *action);
00188 static void gtalk_free_pvt(struct gtalk *client, struct gtalk_pvt *p);
00189 static int gtalk_newcall(struct gtalk *client, ikspak *pak);
00190 static struct ast_frame *gtalk_read(struct ast_channel *ast);
00191 static int gtalk_write(struct ast_channel *ast, struct ast_frame *f);
00192 static int gtalk_indicate(struct ast_channel *ast, int condition, const void *data, size_t datalen);
00193 static int gtalk_fixup(struct ast_channel *oldchan, struct ast_channel *newchan);
00194 static int gtalk_sendhtml(struct ast_channel *ast, int subclass, const char *data, int datalen);
00195 static struct gtalk_pvt *gtalk_alloc(struct gtalk *client, const char *us, const char *them, const char *sid);
00196 static int gtalk_do_reload(int fd, int argc, char **argv);
00197 static int gtalk_show_channels(int fd, int argc, char **argv);
00198
00199 static int gtalk_set_rtp_peer(struct ast_channel *chan, struct ast_rtp *rtp,
00200 struct ast_rtp *vrtp, int codecs, int nat_active);
00201 static enum ast_rtp_get_result gtalk_get_rtp_peer(struct ast_channel *chan, struct ast_rtp **rtp);
00202 static int gtalk_get_codec(struct ast_channel *chan);
00203
00204
00205 static const struct ast_channel_tech gtalk_tech = {
00206 .type = "Gtalk",
00207 .description = "Gtalk Channel Driver",
00208 .capabilities = ((AST_FORMAT_MAX_AUDIO << 1) - 1),
00209 .requester = gtalk_request,
00210 .send_digit_begin = gtalk_digit_begin,
00211 .send_digit_end = gtalk_digit_end,
00212 .bridge = ast_rtp_bridge,
00213 .call = gtalk_call,
00214 .hangup = gtalk_hangup,
00215 .answer = gtalk_answer,
00216 .read = gtalk_read,
00217 .write = gtalk_write,
00218 .exception = gtalk_read,
00219 .indicate = gtalk_indicate,
00220 .fixup = gtalk_fixup,
00221 .send_html = gtalk_sendhtml,
00222 .properties = AST_CHAN_TP_WANTSJITTER | AST_CHAN_TP_CREATESJITTER
00223 };
00224
00225 static struct sockaddr_in bindaddr = { 0, };
00226
00227 static struct sched_context *sched;
00228 static struct io_context *io;
00229 static struct in_addr __ourip;
00230
00231
00232
00233 static struct ast_rtp_protocol gtalk_rtp = {
00234 type: "Gtalk",
00235 get_rtp_info: gtalk_get_rtp_peer,
00236 set_rtp_peer: gtalk_set_rtp_peer,
00237 get_codec: gtalk_get_codec,
00238 };
00239
00240 static char show_channels_usage[] =
00241 "Usage: gtalk show channels\n"
00242 " Shows current state of the Gtalk channels.\n";
00243
00244 static char reload_usage[] =
00245 "Usage: gtalk reload\n"
00246 " Reload gtalk channel driver.\n";
00247
00248
00249 static struct ast_cli_entry gtalk_cli[] = {
00250 {{ "gtalk", "reload", NULL}, gtalk_do_reload, "Reload GoogleTalk configuration", reload_usage },
00251 {{ "gtalk", "show", "channels", NULL}, gtalk_show_channels, "Show GoogleTalk channels", show_channels_usage },
00252 };
00253
00254
00255
00256 static char externip[16];
00257
00258 static struct gtalk_container gtalk_list;
00259
00260 static void gtalk_member_destroy(struct gtalk *obj)
00261 {
00262 free(obj);
00263 }
00264
00265 static struct gtalk *find_gtalk(char *name, char *connection)
00266 {
00267 struct gtalk *gtalk = NULL;
00268 char *domain = NULL , *s = NULL;
00269
00270 if(strchr(connection, '@')) {
00271 s = ast_strdupa(connection);
00272 domain = strsep(&s, "@");
00273 ast_verbose("OOOOH domain = %s\n", domain);
00274 }
00275 gtalk = ASTOBJ_CONTAINER_FIND(>alk_list, name);
00276 if (!gtalk && strchr(name, '@'))
00277 gtalk = ASTOBJ_CONTAINER_FIND_FULL(>alk_list, name, user,,, strcasecmp);
00278
00279 if (!gtalk) {
00280
00281 ASTOBJ_CONTAINER_TRAVERSE(>alk_list, 1, {
00282 ASTOBJ_RDLOCK(iterator);
00283 if (!strcasecmp(iterator->name, "guest")) {
00284 gtalk = iterator;
00285 }
00286 ASTOBJ_UNLOCK(iterator);
00287
00288 if (gtalk)
00289 break;
00290 });
00291
00292 }
00293 return gtalk;
00294 }
00295
00296
00297 static int add_codec_to_answer(const struct gtalk_pvt *p, int codec, iks *dcodecs)
00298 {
00299 int res = 0;
00300 char *format = ast_getformatname(codec);
00301
00302 if (!strcasecmp("ulaw", format)) {
00303 iks *payload_eg711u, *payload_pcmu;
00304 payload_pcmu = iks_new("payload-type");
00305 payload_eg711u = iks_new("payload-type");
00306
00307 if(!payload_eg711u || !payload_pcmu) {
00308 if(payload_pcmu)
00309 iks_delete(payload_pcmu);
00310 if(payload_eg711u)
00311 iks_delete(payload_eg711u);
00312 ast_log(LOG_WARNING,"Failed to allocate iks node");
00313 return -1;
00314 }
00315 iks_insert_attrib(payload_pcmu, "id", "0");
00316 iks_insert_attrib(payload_pcmu, "name", "PCMU");
00317 iks_insert_attrib(payload_pcmu, "clockrate","8000");
00318 iks_insert_attrib(payload_pcmu, "bitrate","64000");
00319 iks_insert_attrib(payload_eg711u, "id", "100");
00320 iks_insert_attrib(payload_eg711u, "name", "EG711U");
00321 iks_insert_attrib(payload_eg711u, "clockrate","8000");
00322 iks_insert_attrib(payload_eg711u, "bitrate","64000");
00323 iks_insert_node(dcodecs, payload_pcmu);
00324 iks_insert_node(dcodecs, payload_eg711u);
00325 res ++;
00326 }
00327 if (!strcasecmp("alaw", format)) {
00328 iks *payload_eg711a, *payload_pcma;
00329 payload_pcma = iks_new("payload-type");
00330 payload_eg711a = iks_new("payload-type");
00331 if(!payload_eg711a || !payload_pcma) {
00332 if(payload_eg711a)
00333 iks_delete(payload_eg711a);
00334 if(payload_pcma)
00335 iks_delete(payload_pcma);
00336 ast_log(LOG_WARNING,"Failed to allocate iks node");
00337 return -1;
00338 }
00339 iks_insert_attrib(payload_pcma, "id", "8");
00340 iks_insert_attrib(payload_pcma, "name", "PCMA");
00341 iks_insert_attrib(payload_pcma, "clockrate","8000");
00342 iks_insert_attrib(payload_pcma, "bitrate","64000");
00343 payload_eg711a = iks_new("payload-type");
00344 iks_insert_attrib(payload_eg711a, "id", "101");
00345 iks_insert_attrib(payload_eg711a, "name", "EG711A");
00346 iks_insert_attrib(payload_eg711a, "clockrate","8000");
00347 iks_insert_attrib(payload_eg711a, "bitrate","64000");
00348 iks_insert_node(dcodecs, payload_pcma);
00349 iks_insert_node(dcodecs, payload_eg711a);
00350 res ++;
00351 }
00352 if (!strcasecmp("ilbc", format)) {
00353 iks *payload_ilbc = iks_new("payload-type");
00354 if(!payload_ilbc) {
00355 ast_log(LOG_WARNING,"Failed to allocate iks node");
00356 return -1;
00357 }
00358 iks_insert_attrib(payload_ilbc, "id", "97");
00359 iks_insert_attrib(payload_ilbc, "name", "iLBC");
00360 iks_insert_attrib(payload_ilbc, "clockrate","8000");
00361 iks_insert_attrib(payload_ilbc, "bitrate","13300");
00362 iks_insert_node(dcodecs, payload_ilbc);
00363 res ++;
00364 }
00365 if (!strcasecmp("g723", format)) {
00366 iks *payload_g723 = iks_new("payload-type");
00367 if(!payload_g723) {
00368 ast_log(LOG_WARNING,"Failed to allocate iks node");
00369 return -1;
00370 }
00371 iks_insert_attrib(payload_g723, "id", "4");
00372 iks_insert_attrib(payload_g723, "name", "G723");
00373 iks_insert_attrib(payload_g723, "clockrate","8000");
00374 iks_insert_attrib(payload_g723, "bitrate","6300");
00375 iks_insert_node(dcodecs, payload_g723);
00376 res ++;
00377 }
00378 if (!strcasecmp("speex", format)) {
00379 iks *payload_speex = iks_new("payload-type");
00380 if(!payload_speex) {
00381 ast_log(LOG_WARNING,"Failed to allocate iks node");
00382 return -1;
00383 }
00384 iks_insert_attrib(payload_speex, "id", "110");
00385 iks_insert_attrib(payload_speex, "name", "speex");
00386 iks_insert_attrib(payload_speex, "clockrate","8000");
00387 iks_insert_attrib(payload_speex, "bitrate","11000");
00388 iks_insert_node(dcodecs, payload_speex);
00389 res++;
00390 }
00391 if (!strcasecmp("gsm", format)) {
00392 iks *payload_gsm = iks_new("payload-type");
00393 if(!payload_gsm) {
00394 ast_log(LOG_WARNING,"Failed to allocate iks node");
00395 return -1;
00396 }
00397 iks_insert_attrib(payload_gsm, "id", "103");
00398 iks_insert_attrib(payload_gsm, "name", "gsm");
00399 iks_insert_node(dcodecs, payload_gsm);
00400 res++;
00401 }
00402 ast_rtp_lookup_code(p->rtp, 1, codec);
00403 return res;
00404 }
00405
00406 static int gtalk_invite(struct gtalk_pvt *p, char *to, char *from, char *sid, int initiator)
00407 {
00408 struct gtalk *client = p->parent;
00409 iks *iq, *gtalk, *dcodecs, *payload_telephone, *transport;
00410 int x;
00411 int pref_codec = 0;
00412 int alreadysent = 0;
00413 int codecs_num = 0;
00414
00415 iq = iks_new("iq");
00416 gtalk = iks_new("session");
00417 dcodecs = iks_new("description");
00418 transport = iks_new("transport");
00419 payload_telephone = iks_new("payload-type");
00420 if (!(iq && gtalk && dcodecs && transport && payload_telephone)){
00421 if(iq)
00422 iks_delete(iq);
00423 if(gtalk)
00424 iks_delete(gtalk);
00425 if(dcodecs)
00426 iks_delete(dcodecs);
00427 if(transport)
00428 iks_delete(transport);
00429 if(payload_telephone)
00430 iks_delete(payload_telephone);
00431
00432 ast_log(LOG_ERROR, "Could not allocate iksemel nodes\n");
00433 return 0;
00434 }
00435 iks_insert_attrib(dcodecs, "xmlns", "http://www.google.com/session/phone");
00436 iks_insert_attrib(dcodecs, "xml:lang", "en");
00437
00438 for (x = 0; x < 32; x++) {
00439 if (!(pref_codec = ast_codec_pref_index(&client->prefs, x)))
00440 break;
00441 if (!(client->capability & pref_codec))
00442 continue;
00443 if (alreadysent & pref_codec)
00444 continue;
00445 codecs_num = add_codec_to_answer(p, pref_codec, dcodecs);
00446 alreadysent |= pref_codec;
00447 }
00448
00449 if (codecs_num) {
00450
00451 iks_insert_attrib(payload_telephone, "id", "106");
00452 iks_insert_attrib(payload_telephone, "name", "telephone-event");
00453 iks_insert_attrib(payload_telephone, "clockrate", "8000");
00454 }
00455 iks_insert_attrib(transport,"xmlns","http://www.google.com/transport/p2p");
00456
00457 iks_insert_attrib(iq, "type", "set");
00458 iks_insert_attrib(iq, "to", to);
00459 iks_insert_attrib(iq, "from", from);
00460 iks_insert_attrib(iq, "id", client->connection->mid);
00461 ast_aji_increment_mid(client->connection->mid);
00462
00463 iks_insert_attrib(gtalk, "xmlns", "http://www.google.com/session");
00464 iks_insert_attrib(gtalk, "type",initiator ? "initiate": "accept");
00465 iks_insert_attrib(gtalk, "initiator", initiator ? from : to);
00466 iks_insert_attrib(gtalk, "id", sid);
00467 iks_insert_node(iq, gtalk);
00468 iks_insert_node(gtalk, dcodecs);
00469 iks_insert_node(gtalk, transport);
00470 iks_insert_node(dcodecs, payload_telephone);
00471
00472 iks_send(client->connection->p, iq);
00473 iks_delete(payload_telephone);
00474 iks_delete(transport);
00475 iks_delete(dcodecs);
00476 iks_delete(gtalk);
00477 iks_delete(iq);
00478 return 1;
00479 }
00480
00481 static int gtalk_invite_response(struct gtalk_pvt *p, char *to , char *from, char *sid, int initiator)
00482 {
00483 iks *iq, *session, *transport;
00484 iq = iks_new("iq");
00485 session = iks_new("session");
00486 transport = iks_new("transport");
00487 if(!(iq && session && transport)) {
00488 if(iq)
00489 iks_delete(iq);
00490 if(session)
00491 iks_delete(session);
00492 if(transport)
00493 iks_delete(transport);
00494 ast_log(LOG_ERROR, " Unable to allocate IKS node\n");
00495 return -1;
00496 }
00497 iks_insert_attrib(iq, "from", from);
00498 iks_insert_attrib(iq, "to", to);
00499 iks_insert_attrib(iq, "type", "set");
00500 iks_insert_attrib(iq, "id",p->parent->connection->mid);
00501 ast_aji_increment_mid(p->parent->connection->mid);
00502 iks_insert_attrib(session, "type", "transport-accept");
00503 iks_insert_attrib(session, "id", sid);
00504 iks_insert_attrib(session, "initiator", initiator ? from : to);
00505 iks_insert_attrib(session, "xmlns", "http://www.google.com/session");
00506 iks_insert_attrib(transport, "xmlns", "http://www.google.com/transport/p2p");
00507 iks_insert_node(iq,session);
00508 iks_insert_node(session,transport);
00509 iks_send(p->parent->connection->p, iq);
00510 iks_delete(transport);
00511 iks_delete(session);
00512 iks_delete(iq);
00513 return 1;
00514
00515 }
00516
00517 static int gtalk_ringing_ack(void *data, ikspak *pak)
00518 {
00519 struct gtalk_pvt *p = data;
00520
00521 if (p->ringrule)
00522 iks_filter_remove_rule(p->parent->connection->f, p->ringrule);
00523 p->ringrule = NULL;
00524 if (p->owner)
00525 ast_queue_control(p->owner, AST_CONTROL_RINGING);
00526 return IKS_FILTER_EAT;
00527 }
00528
00529 static int gtalk_answer(struct ast_channel *ast)
00530 {
00531 struct gtalk_pvt *p = ast->tech_pvt;
00532 int res = 0;
00533
00534 if (option_debug)
00535 ast_log(LOG_DEBUG, "Answer!\n");
00536 ast_mutex_lock(&p->lock);
00537 gtalk_invite(p, p->them, p->us,p->sid, 0);
00538 ast_mutex_unlock(&p->lock);
00539 return res;
00540 }
00541
00542 static enum ast_rtp_get_result gtalk_get_rtp_peer(struct ast_channel *chan, struct ast_rtp **rtp)
00543 {
00544 struct gtalk_pvt *p = chan->tech_pvt;
00545 enum ast_rtp_get_result res = AST_RTP_GET_FAILED;
00546
00547 if (!p)
00548 return res;
00549
00550 ast_mutex_lock(&p->lock);
00551 if (p->rtp){
00552 *rtp = p->rtp;
00553 res = AST_RTP_TRY_PARTIAL;
00554 }
00555 ast_mutex_unlock(&p->lock);
00556
00557 return res;
00558 }
00559
00560 static int gtalk_get_codec(struct ast_channel *chan)
00561 {
00562 struct gtalk_pvt *p = chan->tech_pvt;
00563 return p->peercapability;
00564 }
00565
00566 static int gtalk_set_rtp_peer(struct ast_channel *chan, struct ast_rtp *rtp, struct ast_rtp *vrtp, int codecs, int nat_active)
00567 {
00568 struct gtalk_pvt *p;
00569
00570 p = chan->tech_pvt;
00571 if (!p)
00572 return -1;
00573 ast_mutex_lock(&p->lock);
00574
00575
00576
00577
00578
00579
00580
00581
00582 ast_mutex_unlock(&p->lock);
00583 return 0;
00584 }
00585
00586 static int gtalk_response(struct gtalk *client, char *from, ikspak *pak, const char *reasonstr, const char *reasonstr2)
00587 {
00588 iks *response = NULL, *error = NULL, *reason = NULL;
00589 int res = -1;
00590
00591 response = iks_new("iq");
00592 if (response) {
00593 iks_insert_attrib(response, "type", "result");
00594 iks_insert_attrib(response, "from", from);
00595 iks_insert_attrib(response, "to", iks_find_attrib(pak->x, "from"));
00596 iks_insert_attrib(response, "id", iks_find_attrib(pak->x, "id"));
00597 if (reasonstr) {
00598 error = iks_new("error");
00599 if (error) {
00600 iks_insert_attrib(error, "type", "cancel");
00601 reason = iks_new(reasonstr);
00602 if (reason)
00603 iks_insert_node(error, reason);
00604 iks_insert_node(response, error);
00605 }
00606 }
00607 iks_send(client->connection->p, response);
00608 if (reason)
00609 iks_delete(reason);
00610 if (error)
00611 iks_delete(error);
00612 iks_delete(response);
00613 res = 0;
00614 }
00615 return res;
00616 }
00617
00618 static int gtalk_is_answered(struct gtalk *client, ikspak *pak)
00619 {
00620 struct gtalk_pvt *tmp;
00621 char *from;
00622 iks *codec;
00623 char s1[BUFSIZ], s2[BUFSIZ], s3[BUFSIZ];
00624 int peernoncodeccapability;
00625
00626 ast_log(LOG_DEBUG, "The client is %s\n", client->name);
00627
00628 for (tmp = client->p; tmp; tmp = tmp->next) {
00629 if (iks_find_with_attrib(pak->x, "session", "id", tmp->sid))
00630 break;
00631 }
00632
00633
00634 codec = iks_child(iks_child(iks_child(pak->x)));
00635 while (codec) {
00636 ast_rtp_set_m_type(tmp->rtp, atoi(iks_find_attrib(codec, "id")));
00637 ast_rtp_set_rtpmap_type(tmp->rtp, atoi(iks_find_attrib(codec, "id")), "audio", iks_find_attrib(codec, "name"), 0);
00638 codec = iks_next(codec);
00639 }
00640
00641
00642 ast_rtp_get_current_formats(tmp->rtp, &tmp->peercapability, &peernoncodeccapability);
00643
00644
00645
00646 tmp->jointcapability = tmp->capability & tmp->peercapability;
00647 if (!tmp->jointcapability) {
00648 ast_log(LOG_WARNING, "Capabilities don't match : us - %s, peer - %s, combined - %s \n", ast_getformatname_multiple(s1, BUFSIZ, tmp->capability),
00649 ast_getformatname_multiple(s2, BUFSIZ, tmp->peercapability),
00650 ast_getformatname_multiple(s3, BUFSIZ, tmp->jointcapability));
00651
00652 ast_queue_hangup(tmp->owner);
00653
00654 return -1;
00655
00656 }
00657
00658 from = iks_find_attrib(pak->x, "to");
00659 if(!from)
00660 from = client->connection->jid->full;
00661
00662 if (tmp) {
00663 if (tmp->owner)
00664 ast_queue_control(tmp->owner, AST_CONTROL_ANSWER);
00665 } else
00666 ast_log(LOG_NOTICE, "Whoa, didn't find call!\n");
00667 gtalk_response(client, from, pak, NULL, NULL);
00668 return 1;
00669 }
00670
00671 static int gtalk_is_accepted(struct gtalk *client, ikspak *pak)
00672 {
00673 struct gtalk_pvt *tmp;
00674 char *from;
00675
00676 ast_log(LOG_DEBUG, "The client is %s\n", client->name);
00677
00678 for (tmp = client->p; tmp; tmp = tmp->next) {
00679 if (iks_find_with_attrib(pak->x, "session", "id", tmp->sid))
00680 break;
00681 }
00682
00683 from = iks_find_attrib(pak->x, "to");
00684 if(!from)
00685 from = client->connection->jid->full;
00686
00687 if (!tmp)
00688 ast_log(LOG_NOTICE, "Whoa, didn't find call!\n");
00689
00690
00691 gtalk_response(client, from, pak, NULL, NULL);
00692 return 1;
00693 }
00694
00695 static int gtalk_handle_dtmf(struct gtalk *client, ikspak *pak)
00696 {
00697 struct gtalk_pvt *tmp;
00698 iks *dtmfnode = NULL, *dtmfchild = NULL;
00699 char *dtmf;
00700 char *from;
00701
00702 for (tmp = client->p; tmp; tmp = tmp->next) {
00703 if (iks_find_with_attrib(pak->x, "session", "id", tmp->sid) || iks_find_with_attrib(pak->x, "gtalk", "sid", tmp->sid))
00704 break;
00705 }
00706 from = iks_find_attrib(pak->x, "to");
00707 if(!from)
00708 from = client->connection->jid->full;
00709
00710
00711 if (tmp) {
00712 if(iks_find_with_attrib(pak->x, "dtmf-method", "method", "rtp")) {
00713 gtalk_response(client, from, pak,
00714 "feature-not-implemented xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'",
00715 "unsupported-dtmf-method xmlns='http://jabber.org/protocol/gtalk/info/dtmf#errors'");
00716 return -1;
00717 }
00718 if ((dtmfnode = iks_find(pak->x, "dtmf"))) {
00719 if((dtmf = iks_find_attrib(dtmfnode, "code"))) {
00720 if(iks_find_with_attrib(pak->x, "dtmf", "action", "button-up")) {
00721 struct ast_frame f = {AST_FRAME_DTMF_BEGIN, };
00722 f.subclass = dtmf[0];
00723 ast_queue_frame(tmp->owner, &f);
00724 ast_verbose("GOOGLE! DTMF-relay event received: %c\n", f.subclass);
00725 } else if(iks_find_with_attrib(pak->x, "dtmf", "action", "button-down")) {
00726 struct ast_frame f = {AST_FRAME_DTMF_END, };
00727 f.subclass = dtmf[0];
00728 ast_queue_frame(tmp->owner, &f);
00729 ast_verbose("GOOGLE! DTMF-relay event received: %c\n", f.subclass);
00730 } else if(iks_find_attrib(pak->x, "dtmf")) {
00731 struct ast_frame f = {AST_FRAME_DTMF, };
00732 f.subclass = dtmf[0];
00733 ast_queue_frame(tmp->owner, &f);
00734 ast_verbose("GOOGLE! DTMF-relay event received: %c\n", f.subclass);
00735 }
00736 }
00737 } else if ((dtmfnode = iks_find_with_attrib(pak->x, "gtalk", "action", "session-info"))) {
00738 if((dtmfchild = iks_find(dtmfnode, "dtmf"))) {
00739 if((dtmf = iks_find_attrib(dtmfchild, "code"))) {
00740 if(iks_find_with_attrib(dtmfnode, "dtmf", "action", "button-up")) {
00741 struct ast_frame f = {AST_FRAME_DTMF_END, };
00742 f.subclass = dtmf[0];
00743 ast_queue_frame(tmp->owner, &f);
00744 ast_verbose("GOOGLE! DTMF-relay event received: %c\n", f.subclass);
00745 } else if(iks_find_with_attrib(dtmfnode, "dtmf", "action", "button-down")) {
00746 struct ast_frame f = {AST_FRAME_DTMF_BEGIN, };
00747 f.subclass = dtmf[0];
00748 ast_queue_frame(tmp->owner, &f);
00749 ast_verbose("GOOGLE! DTMF-relay event received: %c\n", f.subclass);
00750 }
00751 }
00752 }
00753 }
00754 gtalk_response(client, from, pak, NULL, NULL);
00755 return 1;
00756 } else
00757 ast_log(LOG_NOTICE, "Whoa, didn't find call!\n");
00758
00759 gtalk_response(client, from, pak, NULL, NULL);
00760 return 1;
00761 }
00762
00763 static int gtalk_hangup_farend(struct gtalk *client, ikspak *pak)
00764 {
00765 struct gtalk_pvt *tmp;
00766 char *from;
00767
00768 ast_log(LOG_DEBUG, "The client is %s\n", client->name);
00769
00770 for (tmp = client->p; tmp; tmp = tmp->next) {
00771 if (iks_find_with_attrib(pak->x, "session", "id", tmp->sid))
00772 break;
00773 }
00774 from = iks_find_attrib(pak->x, "to");
00775 if(!from)
00776 from = client->connection->jid->full;
00777
00778 if (tmp) {
00779 tmp->alreadygone = 1;
00780 if (tmp->owner)
00781 ast_queue_hangup(tmp->owner);
00782 } else
00783 ast_log(LOG_NOTICE, "Whoa, didn't find call!\n");
00784 gtalk_response(client, from, pak, NULL, NULL);
00785 return 1;
00786 }
00787
00788 static int gtalk_create_candidates(struct gtalk *client, struct gtalk_pvt *p, char *sid, char *from, char *to)
00789 {
00790 struct gtalk_candidate *tmp;
00791 struct aji_client *c = client->connection;
00792 struct gtalk_candidate *ours1 = NULL, *ours2 = NULL;
00793 struct sockaddr_in sin;
00794 struct sockaddr_in dest;
00795 struct in_addr us;
00796 iks *iq, *gtalk, *candidate, *transport;
00797 char user[17], pass[17], preference[5], port[7];
00798
00799
00800 iq = iks_new("iq");
00801 gtalk = iks_new("session");
00802 candidate = iks_new("candidate");
00803 transport = iks_new("transport");
00804 if (!iq || !gtalk || !candidate || !transport) {
00805 ast_log(LOG_ERROR, "Memory allocation error\n");
00806 goto safeout;
00807 }
00808 ours1 = ast_calloc(1, sizeof(*ours1));
00809 ours2 = ast_calloc(1, sizeof(*ours2));
00810 if (!ours1 || !ours2)
00811 goto safeout;
00812
00813 iks_insert_attrib(transport, "xmlns","http://www.google.com/transport/p2p");
00814 iks_insert_node(iq, gtalk);
00815 iks_insert_node(gtalk,transport);
00816 iks_insert_node(transport, candidate);
00817
00818 for (; p; p = p->next) {
00819 if (!strcasecmp(p->sid, sid))
00820 break;
00821 }
00822
00823 if (!p) {
00824 ast_log(LOG_NOTICE, "No matching gtalk session - SID %s!\n", sid);
00825 goto safeout;
00826 }
00827
00828 ast_rtp_get_us(p->rtp, &sin);
00829 ast_find_ourip(&us, bindaddr);
00830
00831
00832 ast_copy_string(ours1->name, "rtp", sizeof(ours1->name));
00833 ours1->port = ntohs(sin.sin_port);
00834 ours1->preference = 1;
00835 snprintf(user, sizeof(user), "%08lx%08lx", ast_random(), ast_random());
00836 snprintf(pass, sizeof(pass), "%08lx%08lx", ast_random(), ast_random());
00837 ast_copy_string(ours1->username, user, sizeof(ours1->username));
00838 ast_copy_string(ours1->password, pass, sizeof(ours1->password));
00839 ast_copy_string(ours1->ip, ast_inet_ntoa(us), sizeof(ours1->ip));
00840 ours1->protocol = AJI_PROTOCOL_UDP;
00841 ours1->type = AJI_CONNECT_LOCAL;
00842 ours1->generation = 0;
00843 p->ourcandidates = ours1;
00844
00845 if (!ast_strlen_zero(externip)) {
00846
00847 snprintf(user, sizeof(user), "%08lx%08lx", ast_random(), ast_random());
00848 snprintf(pass, sizeof(pass), "%08lx%08lx", ast_random(), ast_random());
00849 ast_copy_string(ours2->username, user, sizeof(ours2->username));
00850 ast_copy_string(ours2->password, pass, sizeof(ours2->password));
00851 ast_copy_string(ours2->ip, externip, sizeof(ours2->ip));
00852 ast_copy_string(ours2->name, "rtp", sizeof(ours1->name));
00853 ours2->port = ntohs(sin.sin_port);
00854 ours2->preference = 0.9;
00855 ours2->protocol = AJI_PROTOCOL_UDP;
00856 ours2->type = AJI_CONNECT_STUN;
00857 ours2->generation = 0;
00858 ours1->next = ours2;
00859 ours2 = NULL;
00860 }
00861 ours1 = NULL;
00862 dest.sin_addr = __ourip;
00863 dest.sin_port = sin.sin_port;
00864
00865
00866 for (tmp = p->ourcandidates; tmp; tmp = tmp->next) {
00867 snprintf(port, sizeof(port), "%d", tmp->port);
00868 snprintf(preference, sizeof(preference), "%.2f", tmp->preference);
00869 iks_insert_attrib(iq, "from", to);
00870 iks_insert_attrib(iq, "to", from);
00871 iks_insert_attrib(iq, "type", "set");
00872 iks_insert_attrib(iq, "id", c->mid);
00873 ast_aji_increment_mid(c->mid);
00874 iks_insert_attrib(gtalk, "type", "transport-info");
00875 iks_insert_attrib(gtalk, "id", sid);
00876 iks_insert_attrib(gtalk, "initiator", (p->initiator) ? to : from);
00877 iks_insert_attrib(gtalk, "xmlns", GOOGLE_NS);
00878 iks_insert_attrib(candidate, "name", tmp->name);
00879 iks_insert_attrib(candidate, "address", tmp->ip);
00880 iks_insert_attrib(candidate, "port", port);
00881 iks_insert_attrib(candidate, "username", tmp->username);
00882 iks_insert_attrib(candidate, "password", tmp->password);
00883 iks_insert_attrib(candidate, "preference", preference);
00884 if (tmp->