46 #include <sys/socket.h>
49 #include <netinet/in.h>
50 #include <arpa/inet.h>
51 #include <sys/signal.h>
80 #define GOOGLE_CONFIG "gtalk.conf"
87 .resync_threshold = -1,
169 static const char desc[] =
"Gtalk Channel";
203 .description =
"Gtalk Channel Driver",
249 char *domain = NULL , *s = NULL;
251 if (strchr(connection,
'@')) {
257 if (!gtalk && strchr(name,
'@'))
264 if (!strcasecmp(iterator->name,
"guest")) {
283 if (!strcasecmp(
"ulaw", format)) {
284 iks *payload_eg711u, *payload_pcmu;
285 payload_pcmu = iks_new(
"payload-type");
286 payload_eg711u = iks_new(
"payload-type");
288 if(!payload_eg711u || !payload_pcmu) {
289 iks_delete(payload_pcmu);
290 iks_delete(payload_eg711u);
294 iks_insert_attrib(payload_pcmu,
"id",
"0");
295 iks_insert_attrib(payload_pcmu,
"name",
"PCMU");
296 iks_insert_attrib(payload_pcmu,
"clockrate",
"8000");
297 iks_insert_attrib(payload_pcmu,
"bitrate",
"64000");
298 iks_insert_attrib(payload_eg711u,
"id",
"100");
299 iks_insert_attrib(payload_eg711u,
"name",
"EG711U");
300 iks_insert_attrib(payload_eg711u,
"clockrate",
"8000");
301 iks_insert_attrib(payload_eg711u,
"bitrate",
"64000");
302 iks_insert_node(dcodecs, payload_pcmu);
303 iks_insert_node(dcodecs, payload_eg711u);
306 if (!strcasecmp(
"alaw", format)) {
307 iks *payload_eg711a, *payload_pcma;
308 payload_pcma = iks_new(
"payload-type");
309 payload_eg711a = iks_new(
"payload-type");
310 if(!payload_eg711a || !payload_pcma) {
311 iks_delete(payload_eg711a);
312 iks_delete(payload_pcma);
316 iks_insert_attrib(payload_pcma,
"id",
"8");
317 iks_insert_attrib(payload_pcma,
"name",
"PCMA");
318 iks_insert_attrib(payload_pcma,
"clockrate",
"8000");
319 iks_insert_attrib(payload_pcma,
"bitrate",
"64000");
320 payload_eg711a = iks_new(
"payload-type");
321 iks_insert_attrib(payload_eg711a,
"id",
"101");
322 iks_insert_attrib(payload_eg711a,
"name",
"EG711A");
323 iks_insert_attrib(payload_eg711a,
"clockrate",
"8000");
324 iks_insert_attrib(payload_eg711a,
"bitrate",
"64000");
325 iks_insert_node(dcodecs, payload_pcma);
326 iks_insert_node(dcodecs, payload_eg711a);
329 if (!strcasecmp(
"ilbc", format)) {
330 iks *payload_ilbc = iks_new(
"payload-type");
335 iks_insert_attrib(payload_ilbc,
"id",
"97");
336 iks_insert_attrib(payload_ilbc,
"name",
"iLBC");
337 iks_insert_attrib(payload_ilbc,
"clockrate",
"8000");
338 iks_insert_attrib(payload_ilbc,
"bitrate",
"13300");
339 iks_insert_node(dcodecs, payload_ilbc);
342 if (!strcasecmp(
"g723", format)) {
343 iks *payload_g723 = iks_new(
"payload-type");
348 iks_insert_attrib(payload_g723,
"id",
"4");
349 iks_insert_attrib(payload_g723,
"name",
"G723");
350 iks_insert_attrib(payload_g723,
"clockrate",
"8000");
351 iks_insert_attrib(payload_g723,
"bitrate",
"6300");
352 iks_insert_node(dcodecs, payload_g723);
355 if (!strcasecmp(
"speex", format)) {
356 iks *payload_speex = iks_new(
"payload-type");
361 iks_insert_attrib(payload_speex,
"id",
"110");
362 iks_insert_attrib(payload_speex,
"name",
"speex");
363 iks_insert_attrib(payload_speex,
"clockrate",
"8000");
364 iks_insert_attrib(payload_speex,
"bitrate",
"11000");
365 iks_insert_node(dcodecs, payload_speex);
368 if (!strcasecmp(
"gsm", format)) {
369 iks *payload_gsm = iks_new(
"payload-type");
374 iks_insert_attrib(payload_gsm,
"id",
"103");
375 iks_insert_attrib(payload_gsm,
"name",
"gsm");
376 iks_insert_node(dcodecs, payload_gsm);
386 iks *iq, *
gtalk, *dcodecs, *payload_telephone, *transport;
391 char *lowerto = NULL;
394 gtalk = iks_new(
"session");
395 dcodecs = iks_new(
"description");
396 transport = iks_new(
"transport");
397 payload_telephone = iks_new(
"payload-type");
398 if (!(iq && gtalk && dcodecs && transport && payload_telephone)){
402 iks_delete(transport);
403 iks_delete(payload_telephone);
409 iks_insert_attrib(dcodecs,
"xml:lang",
"en");
411 for (x = 0; x < 64; x++) {
416 if (alreadysent & pref_codec)
419 alreadysent |= pref_codec;
424 iks_insert_attrib(payload_telephone,
"id",
"101");
425 iks_insert_attrib(payload_telephone,
"name",
"telephone-event");
426 iks_insert_attrib(payload_telephone,
"clockrate",
"8000");
430 iks_insert_attrib(iq,
"type",
"set");
431 iks_insert_attrib(iq,
"to", to);
432 iks_insert_attrib(iq,
"from", from);
436 iks_insert_attrib(gtalk,
"xmlns",
GOOGLE_NS);
437 iks_insert_attrib(gtalk,
"type",initiator ?
"initiate":
"accept");
443 while (((c = *t) !=
'/') && (*t++ = tolower(c)));
445 iks_insert_attrib(gtalk,
"initiator", initiator ? from : lowerto);
446 iks_insert_attrib(gtalk,
"id", sid);
447 iks_insert_node(iq, gtalk);
448 iks_insert_node(gtalk, dcodecs);
449 iks_insert_node(dcodecs, payload_telephone);
453 iks_delete(payload_telephone);
454 iks_delete(transport);
474 if (!strcmp(
S_OR(iks_find_attrib(pak->x,
"type"),
""),
"error")) {
476 char *redirect = NULL;
477 iks *traversenodes = NULL;
478 traversenodes = pak->query;
479 while (traversenodes) {
480 if (!(name = iks_name(traversenodes))) {
483 if (!strcasecmp(name,
"error") &&
484 ((redirect = iks_find_cdata(traversenodes,
"redirect")) ||
485 (redirect = iks_find_cdata(traversenodes,
"sta:redirect"))) &&
486 (redirect = strstr(redirect,
"xmpp:"))) {
494 traversenodes = iks_next_tag(traversenodes);
505 return IKS_FILTER_EAT;
574 static int gtalk_response(
struct gtalk *client,
char *from, ikspak *pak,
const char *reasonstr,
const char *reasonstr2)
576 iks *response = NULL, *error = NULL, *reason = NULL;
579 response = iks_new(
"iq");
581 iks_insert_attrib(response,
"type",
"result");
582 iks_insert_attrib(response,
"from", from);
583 iks_insert_attrib(response,
"to",
S_OR(iks_find_attrib(pak->x,
"from"),
""));
584 iks_insert_attrib(response,
"id",
S_OR(iks_find_attrib(pak->x,
"id"),
""));
586 error = iks_new(
"error");
588 iks_insert_attrib(error,
"type",
"cancel");
589 reason = iks_new(reasonstr);
591 iks_insert_node(error, reason);
592 iks_insert_node(response, error);
601 iks_delete(response);
611 char s1[BUFSIZ], s2[BUFSIZ], s3[BUFSIZ];
612 int peernoncodeccapability;
617 for (tmp = client->
p; tmp; tmp = tmp->
next) {
618 if (iks_find_with_attrib(pak->x,
"session",
"id", tmp->
sid)) {
620 }
else if (iks_find_with_attrib(pak->x,
"ses:session",
"id", tmp->
sid)) {
631 codec = iks_first_tag(iks_first_tag(iks_first_tag(pak->x)));
633 char *codec_id = iks_find_attrib(codec,
"id");
634 char *codec_name = iks_find_attrib(codec,
"name");
635 if (!codec_id || !codec_name) {
636 codec = iks_next_tag(codec);
651 codec = iks_next_tag(codec);
671 from = iks_find_attrib(pak->x,
"to");
691 for (tmp = client->
p; tmp; tmp = tmp->
next) {
692 if (iks_find_with_attrib(pak->x,
"session",
"id", tmp->
sid)) {
697 from = iks_find_attrib(pak->x,
"to");
716 iks *dtmfnode = NULL, *dtmfchild = NULL;
720 for (tmp = client->
p; tmp; tmp = tmp->
next) {
721 if (iks_find_with_attrib(pak->x,
"session",
"id", tmp->
sid) || iks_find_with_attrib(pak->x,
"gtalk",
"sid", tmp->
sid))
724 from = iks_find_attrib(pak->x,
"to");
730 if(iks_find_with_attrib(pak->x,
"dtmf-method",
"method",
"rtp")) {
732 "feature-not-implemented xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'",
733 "unsupported-dtmf-method xmlns='http://jabber.org/protocol/gtalk/info/dtmf#errors'");
736 if ((dtmfnode = iks_find(pak->x,
"dtmf"))) {
737 if((dtmf = iks_find_attrib(dtmfnode,
"code"))) {
738 if(iks_find_with_attrib(pak->x,
"dtmf",
"action",
"button-up")) {
743 }
else if(iks_find_with_attrib(pak->x,
"dtmf",
"action",
"button-down")) {
748 }
else if(iks_find_attrib(pak->x,
"dtmf")) {
755 }
else if ((dtmfnode = iks_find_with_attrib(pak->x,
"gtalk",
"action",
"session-info"))) {
756 if((dtmfchild = iks_find(dtmfnode,
"dtmf"))) {
757 if((dtmf = iks_find_attrib(dtmfchild,
"code"))) {
758 if(iks_find_with_attrib(dtmfnode,
"dtmf",
"action",
"button-up")) {
763 }
else if(iks_find_with_attrib(dtmfnode,
"dtmf",
"action",
"button-down")) {
789 for (tmp = client->
p; tmp; tmp = tmp->
next) {
790 if (iks_find_with_attrib(pak->x,
"session",
"id", tmp->
sid) ||
791 (iks_find_attrib(pak->query,
"id") && !strcmp(iks_find_attrib(pak->query,
"id"), tmp->
sid))) {
795 from = iks_find_attrib(pak->x,
"to");
845 struct sockaddr_in sin = { 0, };
848 iks *iq, *
gtalk, *candidate, *transport;
849 char user[17],
pass[17], preference[5], port[7];
850 char *lowerfrom = NULL;
853 gtalk = iks_new(
"session");
854 candidate = iks_new(
"candidate");
855 transport = iks_new(
"transport");
856 if (!iq || !gtalk || !candidate || !transport) {
862 if (!ours1 || !ours2)
866 iks_insert_node(iq, gtalk);
867 iks_insert_node(gtalk,candidate);
868 iks_insert_node(gtalk,transport);
870 for (; p; p = p->
next) {
871 if (!strcasecmp(p->
sid, sid))
886 ast_log(
LOG_WARNING,
"Found a loopback IP on the system, check your network configuration or set the bindaddr attribute.\n");
891 ours1->
port = ntohs(sin.sin_port);
893 snprintf(user,
sizeof(user),
"%08lx%08lx", (
long unsigned)
ast_random(), (
long unsigned)
ast_random());
894 snprintf(pass,
sizeof(pass),
"%08lx%08lx", (
long unsigned)
ast_random(), (
long unsigned)
ast_random());
913 ours2->port = ntohs(sin.sin_port);
914 ours2->preference = 0.9;
917 ours2->generation = 0;
924 snprintf(port,
sizeof(port),
"%d", tmp->
port);
925 snprintf(preference,
sizeof(preference),
"%.2f", tmp->
preference);
926 iks_insert_attrib(iq,
"from", to);
927 iks_insert_attrib(iq,
"to", from);
928 iks_insert_attrib(iq,
"type",
"set");
929 iks_insert_attrib(iq,
"id", c->
mid);
931 iks_insert_attrib(gtalk,
"type",
"candidates");
932 iks_insert_attrib(gtalk,
"id", sid);
938 while (((c = *t) !=
'/') && (*t++ = tolower(c)));
940 iks_insert_attrib(gtalk,
"initiator", (p->
initiator) ? to : lowerfrom);
941 iks_insert_attrib(gtalk,
"xmlns",
GOOGLE_NS);
942 iks_insert_attrib(candidate,
"name", tmp->
name);
943 iks_insert_attrib(candidate,
"address", tmp->
ip);
944 iks_insert_attrib(candidate,
"port", port);
945 iks_insert_attrib(candidate,
"username", tmp->
username);
946 iks_insert_attrib(candidate,
"password", tmp->
password);
947 iks_insert_attrib(candidate,
"preference", preference);
949 iks_insert_attrib(candidate,
"protocol",
"udp");
951 iks_insert_attrib(candidate,
"protocol",
"ssltcp");
953 iks_insert_attrib(candidate,
"type",
"stun");
955 iks_insert_attrib(candidate,
"type",
"local");
957 iks_insert_attrib(candidate,
"type",
"relay");
958 iks_insert_attrib(candidate,
"network",
"0");
959 iks_insert_attrib(candidate,
"generation",
"0");
971 iks_delete(candidate);
972 iks_delete(transport);
982 char idroster[200] =
"";
983 char *data, *
exten = NULL;
987 if (!sid && !strchr(them,
'/')) {
988 if (!strcasecmp(client->
name,
"guest")) {
993 }
else if (client->
buddy) {
1001 resources = resources->
next;
1004 snprintf(idroster,
sizeof(idroster),
"%s/%s", them, resources->
resource);
1005 }
else if ((*them ==
'+') || (strstr(them,
"@voice.google.com"))) {
1006 snprintf(idroster,
sizeof(idroster),
"%s", them);
1035 bindaddr.sin_family = AF_INET;
1038 ast_log(
LOG_ERROR,
"Failed to create a new RTP instance (possibly an invalid bindaddr?)\n");
1051 }
else if (global_capability) {
1065 if(strchr(tmp->
us,
'/')) {
1067 exten =
strsep(&data,
"/");
1074 tmp->
next = client->
p;
1094 "Gtalk/%s-%04lx", n2, (
long unsigned)(
ast_random() & 0xffff));
1167 "Channel: %s\r\nChanneltype: %s\r\nGtalk-SID: %s\r\n",
1175 iks *request, *session = NULL;
1177 char *lowerthem = NULL;
1179 request = iks_new(
"iq");
1181 iks_insert_attrib(request,
"type",
"set");
1182 iks_insert_attrib(request,
"from", p->
us);
1183 iks_insert_attrib(request,
"to", p->
them);
1186 session = iks_new(
"session");
1188 iks_insert_attrib(session,
"type", action);
1189 iks_insert_attrib(session,
"id", p->
sid);
1195 while (((c = *t) !=
'/') && (*t++ = tolower(c)));
1197 iks_insert_attrib(session,
"initiator", p->
initiator ? p->
us : lowerthem);
1198 iks_insert_attrib(session,
"xmlns",
GOOGLE_NS);
1199 iks_insert_node(request, session);
1205 iks_delete(session);
1206 iks_delete(request);
1216 candidate = candidate->
next;
1230 client->
p = p->
next;
1256 char s1[BUFSIZ], s2[BUFSIZ], s3[BUFSIZ];
1257 int peernoncodeccapability;
1261 from = iks_find_attrib(pak->x,
"to");
1267 if (iks_find_with_attrib(pak->x,
"session",
"id", tmp->
sid) ||
1268 (iks_find_attrib(pak->query,
"id") && !strcmp(iks_find_attrib(pak->query,
"id"), tmp->
sid))) {
1276 if (!strcasecmp(client->
name,
"guest")){
1284 ast_log(
LOG_ERROR,
"No XMPP client to talk to, us (partial JID) : %s\n", from);
1289 if (!(sid = iks_find_attrib(pak->query,
"id"))) {
1290 ast_log(
LOG_WARNING,
"Received Initiate without id attribute. Can not start call.\n");
1294 p =
gtalk_alloc(client, from, pak->from->full, sid);
1311 codec = iks_first_tag(iks_first_tag(pak->query));
1314 char *codec_id = iks_find_attrib(codec,
"id");
1315 char *codec_name = iks_find_attrib(codec,
"name");
1316 if (!codec_id || !codec_name) {
1317 codec = iks_next_tag(codec);
1320 if (!strcmp(
S_OR(iks_name(codec),
""),
"vid:payload-type") && p->
vrtp) {
1345 codec = iks_next_tag(codec);
1391 struct sockaddr_in answer = { 0, };
1392 struct sockaddr_in *dst;
1400 sock = socket(AF_INET, SOCK_DGRAM, 0);
1419 memcpy(externip, newaddr,
sizeof(externip));
1431 struct sockaddr_in sin = { 0, };
1432 struct sockaddr_in aux = { 0, };
1450 sin.sin_family = AF_INET;
1451 memcpy(&sin.sin_addr, hp->h_addr,
sizeof(sin.sin_addr));
1452 sin.sin_port = htons(tmp->
port);
1462 if (aux.sin_addr.s_addr && (aux.sin_addr.s_addr != sin.sin_addr.s_addr)) {
1468 if (aux.sin_addr.s_addr) {
1469 ast_debug(4,
"Receiving RTP traffic from IP %s, matches with remote candidate's IP %s\n",
ast_inet_ntoa(aux.sin_addr), tmp->
ip);
1470 ast_debug(4,
"Sending STUN request to %s\n", tmp->
ip);
1480 struct gtalk_pvt *p = NULL, *tmp = NULL;
1483 iks *traversenodes = NULL, *
receipt = NULL;
1486 from = iks_find_attrib(pak->x,
"to");
1488 from = c->
jid->full;
1491 for (tmp = client->
p; tmp; tmp = tmp->
next) {
1492 if (iks_find_with_attrib(pak->x,
"session",
"id", tmp->sid) ||
1493 (iks_find_attrib(pak->query,
"id") && !strcmp(iks_find_attrib(pak->query,
"id"), tmp->sid))) {
1502 traversenodes = pak->query;
1503 while(traversenodes) {
1504 if(!strcasecmp(
S_OR(iks_name(traversenodes),
""),
"session")) {
1505 traversenodes = iks_first_tag(traversenodes);
1508 if(!strcasecmp(
S_OR(iks_name(traversenodes),
""),
"ses:session")) {
1509 traversenodes = iks_child(traversenodes);
1512 if(!strcasecmp(
S_OR(iks_name(traversenodes),
""),
"candidate") || !strcasecmp(
S_OR(iks_name(traversenodes),
""),
"ses:candidate")) {
1513 newcandidate =
ast_calloc(1,
sizeof(*newcandidate));
1517 S_OR(iks_find_attrib(traversenodes,
"name"),
""),
1518 sizeof(newcandidate->
name));
1520 S_OR(iks_find_attrib(traversenodes,
"address"),
""),
1521 sizeof(newcandidate->
ip));
1522 newcandidate->
port = atoi(iks_find_attrib(traversenodes,
"port"));
1524 S_OR(iks_find_attrib(traversenodes,
"username"),
""),
1527 S_OR(iks_find_attrib(traversenodes,
"password"),
""),
1529 newcandidate->
preference = atof(iks_find_attrib(traversenodes,
"preference"));
1530 if (!strcasecmp(
S_OR(iks_find_attrib(traversenodes,
"protocol"),
""),
"udp"))
1532 if (!strcasecmp(
S_OR(iks_find_attrib(traversenodes,
"protocol"),
""),
"ssltcp"))
1535 if (!strcasecmp(
S_OR(iks_find_attrib(traversenodes,
"type"),
""),
"stun"))
1537 if (!strcasecmp(
S_OR(iks_find_attrib(traversenodes,
"type"),
""),
"local"))
1539 if (!strcasecmp(
S_OR(iks_find_attrib(traversenodes,
"type"),
""),
"relay"))
1542 S_OR(iks_find_attrib(traversenodes,
"network"),
""),
1543 sizeof(newcandidate->
network));
1544 newcandidate->
generation = atoi(
S_OR(iks_find_attrib(traversenodes,
"generation"),
"0"));
1545 newcandidate->
next = NULL;
1551 newcandidate = NULL;
1553 traversenodes = iks_next_tag(traversenodes);
1556 receipt = iks_new(
"iq");
1557 iks_insert_attrib(receipt,
"type",
"result");
1558 iks_insert_attrib(receipt,
"from", from);
1559 iks_insert_attrib(receipt,
"to",
S_OR(iks_find_attrib(pak->x,
"from"),
""));
1560 iks_insert_attrib(receipt,
"id",
S_OR(iks_find_attrib(pak->x,
"id"),
""));
1563 iks_delete(receipt);
1619 "Asked to transmit frame type %s, while native formats is %s (read/write = %s/%s)\n",
1660 if ((p->
owner != oldchan)) {
1664 if (p->
owner == oldchan)
1674 switch (condition) {
1682 ast_debug(3,
"Don't know how to indicate condition '%d'\n", condition);
1744 static int gtalk_digit(
struct ast_channel *ast,
char digit,
unsigned int duration)
1748 iks *iq, *
gtalk, *dtmf;
1749 char buffer[2] = {digit,
'\0'};
1750 char *lowerthem = NULL;
1752 gtalk = iks_new(
"gtalk");
1753 dtmf = iks_new(
"dtmf");
1754 if(!iq || !gtalk || !dtmf) {
1762 iks_insert_attrib(iq,
"type",
"set");
1763 iks_insert_attrib(iq,
"to", p->
them);
1764 iks_insert_attrib(iq,
"from", p->
us);
1767 iks_insert_attrib(gtalk,
"xmlns",
"http://jabber.org/protocol/gtalk");
1768 iks_insert_attrib(gtalk,
"action",
"session-info");
1774 while (((c = *t) !=
'/') && (*t++ = tolower(c)));
1776 iks_insert_attrib(gtalk,
"initiator", p->
initiator ? p->
us: lowerthem);
1777 iks_insert_attrib(gtalk,
"sid", p->
sid);
1778 iks_insert_attrib(dtmf,
"xmlns",
"http://jabber.org/protocol/gtalk/info/dtmf");
1779 iks_insert_attrib(dtmf,
"code", buffer);
1780 iks_insert_node(iq, gtalk);
1781 iks_insert_node(gtalk, dtmf);
1785 iks_insert_attrib(dtmf,
"action",
"button-down");
1787 iks_insert_attrib(dtmf,
"action",
"button-up");
1821 IKS_RULE_ID, p->
ring, IKS_RULE_DONE);
1835 struct gtalk *client;
1856 struct gtalk *client = NULL;
1857 char *sender = NULL, *to = NULL, *s = NULL;
1862 sender =
strsep(&s,
"/");
1863 if (sender && (sender[0] !=
'\0')) {
1867 ast_log(
LOG_ERROR,
"Bad arguments in Gtalk Dialstring: %s\n", (
char*) data);
1877 if (!strcasecmp(client->
name,
"guest")){
1885 ast_log(
LOG_ERROR,
"No XMPP client to talk to, us (partial JID) : %s\n", sender);
1903 #define FORMAT "%-30.30s %-30.30s %-15.15s %-5.5s %-5.5s \n"
1909 char *resource = NULL;
1913 e->
command =
"gtalk show channels";
1915 "Usage: gtalk show channels\n"
1916 " Shows current state of the Gtalk channels.\n";
1926 ast_cli(a->
fd,
FORMAT,
"Channel",
"Jabber ID",
"Resource",
"Read",
"Write");
1934 resource = strchr(them,
'/');
1959 ast_cli(a->
fd,
"%d active gtalk channel%s\n", numchans, (numchans != 1) ?
"s" :
"");
1973 "Usage: gtalk reload\n"
1974 " Reload gtalk channel driver.\n";
1987 struct gtalk *client =
ASTOBJ_REF((
struct gtalk *) data);
1991 if (!strcasecmp(iks_name(pak->query),
"jin:jingle") && (tmp = iks_next(pak->query)) && !strcasecmp(iks_name(tmp),
"ses:session")) {
1992 ast_debug(1,
"New method detected. Skipping jingle offer and using old gtalk method.\n");
1996 if (!strcmp(
S_OR(iks_find_attrib(pak->x,
"type"),
""),
"error")) {
1997 ast_log(
LOG_NOTICE,
"Remote peer reported an error, trying to establish the call anyway\n");
2002 }
else if (!strcmp(iks_find_attrib(pak->query,
"type"),
"initiate")) {
2005 }
else if (!strcmp(iks_find_attrib(pak->query,
"type"),
"candidates") || !strcmp(iks_find_attrib(pak->query,
"type"),
"transport-info")) {
2006 ast_debug(3,
"About to add candidate!\n");
2013 }
else if (!strcmp(iks_find_attrib(pak->query,
"type"),
"accept")) {
2015 }
else if (!strcmp(iks_find_attrib(pak->query,
"type"),
"transport-accept")) {
2017 }
else if (!strcmp(iks_find_attrib(pak->query,
"type"),
"content-info") || iks_find_with_attrib(pak->x,
"gtalk",
"action",
"session-info")) {
2019 }
else if (!strcmp(iks_find_attrib(pak->query,
"type"),
"terminate")) {
2021 }
else if (!strcmp(iks_find_attrib(pak->query,
"type"),
"reject")) {
2025 return IKS_FILTER_EAT;
2043 if (!strcasecmp(var->
name,
"username"))
2045 else if (!strcasecmp(var->
name,
"disallow"))
2047 else if (!strcasecmp(var->
name,
"allow"))
2049 else if (!strcasecmp(var->
name,
"context"))
2051 else if (!strcasecmp(var->
name,
"parkinglot"))
2053 else if (!strcasecmp(var->
name,
"connection")) {
2057 IKS_RULE_TYPE, IKS_PAK_IQ,
2058 IKS_RULE_FROM_PARTIAL, member->
user,
2112 if (!strcasecmp(var->
name,
"allowguest")) {
2114 }
else if (!strcasecmp(var->
name,
"disallow")) {
2116 }
else if (!strcasecmp(var->
name,
"allow")) {
2118 }
else if (!strcasecmp(var->
name,
"context")) {
2120 }
else if (!strcasecmp(var->
name,
"externip")) {
2122 }
else if (!strcasecmp(var->
name,
"parkinglot")) {
2124 }
else if (!strcasecmp(var->
name,
"bindaddr")) {
2128 memcpy(&bindaddr.sin_addr, hp->h_addr,
sizeof(bindaddr.sin_addr));
2130 }
else if (!strcasecmp(var->
name,
"stunaddr")) {
2138 if (strcasecmp(cat,
"general")) {
2143 if (!strcasecmp(cat,
"guest")) {
2151 if (!strcasecmp(var->
name,
"disallow")) {
2154 }
else if (!strcasecmp(var->
name,
"allow")) {
2157 }
else if (!strcasecmp(var->
name,
"context")) {
2160 }
else if (!strcasecmp(var->
name,
"parkinglot")) {
2176 iks_filter_add_rule(iterator->f,
gtalk_parser, member, IKS_RULE_TYPE, IKS_PAK_IQ, IKS_RULE_NS,
GOOGLE_NS, IKS_RULE_DONE);
2178 iks_filter_add_rule(iterator->f,
gtalk_parser, member, IKS_RULE_TYPE, IKS_PAK_IQ, IKS_RULE_NS,
"http://jabber.org/protocol/gtalk", IKS_RULE_DONE);
2211 free(jabber_loaded);
2212 if (!jabber_loaded) {
2215 free(jabber_loaded);
2216 if (!jabber_loaded) {
2277 privates = iterator->p;
2279 if (privates->
owner)
2281 privates = privates->
next;
static char * ast_sockaddr_stringify_addr(const struct ast_sockaddr *addr)
Wrapper around ast_sockaddr_stringify_fmt() to return an address only.
Jingle definitions for chan_jingle.
void ast_rtp_codecs_packetization_set(struct ast_rtp_codecs *codecs, struct ast_rtp_instance *instance, struct ast_codec_pref *prefs)
Set codec packetization preferences.
static enum ast_rtp_glue_result gtalk_get_rtp_peer(struct ast_channel *chan, struct ast_rtp_instance **instance)
static char musicclass[MAX_MUSICCLASS]
int ast_queue_hangup(struct ast_channel *chan)
Queue a hangup frame.
unsigned long long ast_group_t
union ast_frame_subclass subclass
int ast_hangup(struct ast_channel *chan)
Hang up a channel.
static char accountcode[AST_MAX_ACCOUNT_CODE]
int presentation
Q.931 encoded presentation-indicator encoded field.
static int gtalk_hangup(struct ast_channel *ast)
Hangup a call through the gtalk proxy channel.
static format_t global_capability
static char exten[AST_MAX_EXTENSION]
Main Channel structure associated with a channel.
struct aji_client * connection
#define AST_CLI_DEFINE(fn, txt,...)
static int gtalk_ringing_ack(void *data, ikspak *pak)
Asterisk locking-related definitions:
Asterisk main include file. File version handling, generic pbx functions.
static struct ast_channel * gtalk_new(struct gtalk *client, struct gtalk_pvt *i, int state, const char *title, const char *linkedid)
Start new gtalk channel.
struct ast_rtp_instance * rtp
void ast_aji_buddy_destroy(struct aji_buddy *obj)
const char * ast_variable_retrieve(const struct ast_config *config, const char *category, const char *variable)
Gets a variable.
char * str
Subscriber phone number (Malloced)
void ast_module_unref(struct ast_module *)
static char parkinglot[AST_MAX_CONTEXT]
int ast_queue_control(struct ast_channel *chan, enum ast_control_frame_type control)
Queue a control frame with payload.
struct ast_frame ast_null_frame
struct ast_party_caller caller
Channel Caller ID information.
char * strsep(char **str, const char *delims)
static char * gtalk_show_channels(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
CLI command "gtalk show channels".
static void gtalk_free_candidates(struct gtalk_candidate *candidate)
static struct ast_frame * gtalk_rtp_read(struct ast_channel *ast, struct gtalk_pvt *p)
int presentation
Q.931 presentation-indicator and screening-indicator encoded fields.
int ast_rtp_instance_dtmf_mode_set(struct ast_rtp_instance *instance, enum ast_rtp_dtmf_mode dtmf_mode)
Set the DTMF mode that should be used.
char them[AJI_MAX_JIDLEN]
CallerID (and other GR30) management and generation Includes code and algorithms from the Zapata libr...
static int gtalk_load_config(void)
static struct ast_jb_conf default_jbconf
static struct io_context * io
int ast_aji_send(struct aji_client *client, iks *x)
Wraps raw sending.
int ast_find_ourip(struct ast_sockaddr *ourip, const struct ast_sockaddr *bindaddr, int family)
Find our IP address.
int ast_cli_unregister_multiple(struct ast_cli_entry *e, int len)
Unregister multiple commands.
#define AST_CAUSE_SWITCH_CONGESTION
static void ast_sockaddr_copy(struct ast_sockaddr *dst, const struct ast_sockaddr *src)
Copies the data from one ast_sockaddr to another.
struct ast_party_name name
Subscriber name.
static int gtalk_sendhtml(struct ast_channel *ast, int subclass, const char *data, int datalen)
void ast_channel_unregister(const struct ast_channel_tech *tech)
Unregister a channel technology.
struct ast_rtp_instance * vrtp
char context[AST_MAX_CONTEXT]
struct ast_channel * ast_channel_release(struct ast_channel *chan)
Unlink and release reference to a channel.
static int gtalk_update_stun(struct gtalk *client, struct gtalk_pvt *p)
struct ast_rtp_codecs * ast_rtp_instance_get_codecs(struct ast_rtp_instance *instance)
Get the codecs structure of an RTP instance.
static int gtalk_hangup_farend(struct gtalk *client, ikspak *pak)
descriptor for a cli entry.
static int gtalk_sendtext(struct ast_channel *ast, const char *text)
enum ast_pbx_result ast_pbx_start(struct ast_channel *c)
Create a new thread and start the PBX.
struct ast_variable * ast_variable_browse(const struct ast_config *config, const char *category)
Goes through variables.
int ast_jb_read_conf(struct ast_jb_conf *conf, const char *varname, const char *value)
Sets jitterbuffer configuration property.
void ast_verbose(const char *fmt,...)
char accountcode[AST_MAX_ACCOUNT_CODE]
static struct gtalk_container gtalk_list
Structure for variables, used for configurations and for channel variables.
enum gtalk_connect_type type
#define AST_MAX_ACCOUNT_CODE
int ast_rtp_instance_write(struct ast_rtp_instance *instance, struct ast_frame *frame)
Send a frame out over RTP.
#define ast_rtp_glue_register(glue)
format_t ast_codec_pref_index(struct ast_codec_pref *pref, int index)
Codec located at a particular place in the preference index.
static struct ast_cli_entry gtalk_cli[]
Configuration File Parser.
static int gtalk_write(struct ast_channel *ast, struct ast_frame *f)
Send frame to media channel (rtp)
uint32_t ast_sockaddr_ipv4(const struct ast_sockaddr *addr)
Get an IPv4 address of an ast_sockaddr.
static struct in_addr __ourip
#define GOOGLE_TRANSPORT_NS
format_t ast_best_codec(format_t fmts)
Pick the best audio codec.
#define ASTOBJ_WRLOCK(object)
Lock an ASTOBJ for writing.
#define ast_mutex_lock(a)
int ast_channel_register(const struct ast_channel_tech *tech)
Register a channel technology (a new channel driver) Called by a channel module to register the kind ...
#define AST_MODULE_INFO(keystr, flags_to_set, desc, fields...)
static int gtalk_set_rtp_peer(struct ast_channel *chan, struct ast_rtp_instance *rtp, struct ast_rtp_instance *vrtp, struct ast_rtp_instance *trtp, format_t codecs, int nat_active)
static int gtalk_parser(void *data, ikspak *pak)
CLI command "gtalk reload".
Generic File Format Support. Should be included by clients of the file handling routines. File service providers should instead include mod_format.h.
static void gtalk_member_destroy(struct gtalk *obj)
I/O Management (derived from Cheops-NG)
Common implementation-independent jitterbuffer stuff.
void ast_cli(int fd, const char *fmt,...)
const ast_string_field linkedid
AJI - The Asterisk Jabber Interface.
static struct gtalk_pvt * gtalk_alloc(struct gtalk *client, const char *us, const char *them, const char *sid)
enum ast_channel_adsicpe adsicpe
void ast_moh_stop(struct ast_channel *chan)
Turn off music on hold on a given channel.
Socket address structure.
void ast_config_destroy(struct ast_config *config)
Destroys a config.
struct ast_channel * ast_channel_alloc(int needqueue, int state, const char *cid_num, const char *cid_name, const char *acctcode, const char *exten, const char *context, const char *linkedid, const int amaflag, const char *name_fmt,...)
static int gtalk_update_externip(void)
int ast_aji_send_chat(struct aji_client *client, const char *address, const char *message)
sends messages.
String fields in structures.
static int unload_module(void)
Reload module.
#define ASTOBJ_COMPONENTS(type)
Add ASTOBJ components to a struct (with locking support).
void ast_rtp_instance_stun_request(struct ast_rtp_instance *instance, struct ast_sockaddr *suggestion, const char *username)
Request that the underlying RTP engine send a STUN BIND request.
#define ASTOBJ_CONTAINER_INIT(container)
Initialize a container.
char context[AST_MAX_CONTEXT]
struct ast_party_id id
Caller party ID.
int ast_set_write_format(struct ast_channel *chan, format_t format)
Sets write format on channel chan Set write format for channel to whichever component of "format" is ...
char resource[AJI_MAX_RESJIDLEN]
#define EVENT_FLAG_SYSTEM
int ast_set_read_format(struct ast_channel *chan, format_t format)
Sets read format on channel chan Set read format for channel to whichever component of "format" is be...
int ast_ouraddrfor(const struct ast_sockaddr *them, struct ast_sockaddr *us)
Get our local IP address when contacting a remote host.
static int gtalk_create_member(char *label, struct ast_variable *var, int allowguest, struct ast_codec_pref prefs, char *context, struct gtalk *member)
#define ast_debug(level,...)
Log a DEBUG message.
int ast_sockaddr_is_any(const struct ast_sockaddr *addr)
Determine if the address type is unspecified, or "any" address.
static int gtalk_handle_dtmf(struct gtalk *client, ikspak *pak)
General Asterisk PBX channel definitions.
static const int STANDARD_STUN_PORT
int ast_parse_arg(const char *arg, enum ast_parse_flags flags, void *result,...)
The argument parsing routine.
struct ast_party_dialed::@155 number
Dialed/Called number.
struct gtalk_candidate * ourcandidates
struct aji_buddy_container buddies
#define ast_sockaddr_from_sin(addr, sin)
Converts a struct sockaddr_in to a struct ast_sockaddr.
static struct ast_jb_conf global_jbconf
char musicclass[MAX_MUSICCLASS]
#define ast_config_load(filename, flags)
Load a config file.
int ast_stun_request(int s, struct sockaddr_in *dst, const char *username, struct sockaddr_in *answer)
Generic STUN request.
char * ast_module_helper(const char *line, const char *word, int pos, int state, int rpos, int needsreload)
Match modules names for the Asterisk cli.
static force_inline int attribute_pure ast_strlen_zero(const char *s)
struct sla_ringing_trunk * last
Access Control of various sorts.
Global IO variables are now in a struct in order to be made threadsafe.
Scheduler Routines (derived from cheops)
char parkinglot[AST_MAX_CONTEXT]
char * ast_category_browse(struct ast_config *config, const char *prev)
Goes through categories.
#define ao2_ref(o, delta)
int ast_softhangup(struct ast_channel *chan, int reason)
Softly hangup up a channel.
long int ast_random(void)
struct ast_codec_pref prefs
#define ASTOBJ_INIT(object)
Initialize an object.
static char language[MAX_LANGUAGE]
char user[AJI_MAX_JIDLEN]
static int gtalk_create_candidates(struct gtalk *client, struct gtalk_pvt *p, char *sid, char *from, char *to)
static int add_codec_to_answer(const struct gtalk_pvt *p, int codec, iks *dcodecs)
struct aji_resource * next
int ast_rtp_codecs_payloads_set_rtpmap_type(struct ast_rtp_codecs *codecs, struct ast_rtp_instance *instance, int payload, char *mimetype, char *mimesubtype, enum ast_rtp_options options)
Record payload information that was seen in an a=rtpmap: SDP line.
Structure to describe a channel "technology", ie a channel driver See for examples: ...
Core PBX routines and definitions.
int ast_queue_frame(struct ast_channel *chan, struct ast_frame *f)
Queue one or more frames to a channel's frame queue.
static struct sched_context * sched
#define ASTOBJ_UNREF(object, destructor)
Decrement the reference count on an object.
static int gtalk_indicate(struct ast_channel *ast, int condition, const void *data, size_t datalen)
struct ast_party_dialed dialed
Dialed/Called information.
The AMI - Asterisk Manager Interface - is a TCP protocol created to manage Asterisk with third-party ...
#define ast_strdupa(s)
duplicate a string in memory from the stack
ASTOBJ_CONTAINER_COMPONENTS(struct gtalk)
static int gtalk_is_accepted(struct gtalk *client, ikspak *pak)
char * ast_getformatname(format_t format)
Get the name of a format.
#define ASTOBJ_CONTAINER_DESTROY(container)
Destroy a container.
#define ASTOBJ_CONTAINER_DESTROYALL(container, destructor)
Empty a container.
A set of macros implementing objects and containers. Macros are used for maximum performance, to support multiple inheritance, and to be easily integrated into existing structures without additional malloc calls, etc.
int attribute_pure ast_true(const char *val)
Make sure something is true. Determine if a string containing a boolean value is "true". This function checks to see whether a string passed to it is an indication of an "true" value. It checks to see if the string is "yes", "true", "y", "t", "on" or "1".
static struct sockaddr_in stunaddr
#define ASTOBJ_CONTAINER_LINK(container, newobj)
Add an object to a container.
struct ast_channel * owner
static struct ast_codec_pref prefs
static int gtalk_invite(struct gtalk_pvt *p, char *to, char *from, char *sid, int initiator)
static int gtalk_digit_end(struct ast_channel *ast, char digit, unsigned int duration)
enum ast_channel_state _state
int ast_rtp_instance_dtmf_begin(struct ast_rtp_instance *instance, char digit)
Begin sending a DTMF digit.
static char * ast_sockaddr_stringify(const struct ast_sockaddr *addr)
Wrapper around ast_sockaddr_stringify_fmt() with default format.
const ast_string_field name
int ast_moh_start(struct ast_channel *chan, const char *mclass, const char *interpclass)
Turn on music on hold on a given channel.
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
format_t ast_codec_choose(struct ast_codec_pref *pref, format_t formats, int find_best)
Select the best audio format according to preference list from supplied options. If "find_best" is no...
#define ASTOBJ_CONTAINER_TRAVERSE(container, continue, eval)
Iterate through the objects in a container.
struct aji_client * ast_aji_get_client(const char *name)
grab a aji_client structure by label name or JID. Bumps the refcount. (without the resource string) ...
#define AST_FORMAT_VIDEO_MASK
const char * ast_inet_ntoa(struct in_addr ia)
thread-safe replacement for inet_ntoa().
#define ASTOBJ_UNLOCK(object)
Unlock a locked object.
#define ASTOBJ_CONTAINER_FIND(container, namestr)
Find an object in a container.
#define AST_FORMAT_AUDIO_MASK
void ast_rtp_instance_get_remote_address(struct ast_rtp_instance *instance, struct ast_sockaddr *address)
Get the address of the remote endpoint that we are sending RTP to.
int ast_rtp_instance_fd(struct ast_rtp_instance *instance, int rtcp)
Get the file descriptor for an RTP session (or RTCP)
struct ast_rtp_instance * ast_rtp_instance_new(const char *engine_name, struct sched_context *sched, const struct ast_sockaddr *sa, void *data)
Create a new RTP instance.
unsigned int flags
Combination of the AST_JB_ENABLED, AST_JB_FORCED and AST_JB_LOG flags.
structure to hold users read from users.conf
void ast_rtp_codecs_payloads_clear(struct ast_rtp_codecs *codecs, struct ast_rtp_instance *instance)
Clear payload information from an RTP instance.
void ast_rtp_instance_get_local_address(struct ast_rtp_instance *instance, struct ast_sockaddr *address)
Get the local address that we are expecting RTP on.
Structure used to handle boolean flags.
static struct aji_client_container clients
int ast_rtp_instance_destroy(struct ast_rtp_instance *instance)
Destroy an RTP instance.
void ast_channel_set_fd(struct ast_channel *chan, int which, int fd)
static int gtalk_call(struct ast_channel *ast, char *dest, int timeout)
Initiate new call, part of PBX interface dest is the dial string.
void ast_jb_configure(struct ast_channel *chan, const struct ast_jb_conf *conf)
Configures a jitterbuffer on a channel.
static struct ast_frame * gtalk_read(struct ast_channel *ast)
static struct sockaddr_in bindaddr
void ast_aji_client_destroy(struct aji_client *obj)
static int gtalk_newcall(struct gtalk *client, ikspak *pak)
static struct gtalk * find_gtalk(char *name, char *connection)
struct hostent * ast_gethostbyname(const char *host, struct ast_hostent *hp)
Thread-safe gethostbyname function to use in Asterisk.
static int gtalk_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
struct sched_context * sched_context_create(void)
New schedule context.
Channels have this property if they can create jitter; i.e. most VoIP channels.
static int gtalk_is_answered(struct gtalk *client, ikspak *pak)
Standard Command Line Interface.
#define ASTOBJ_RDLOCK(object)
Lock an ASTOBJ for reading.
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one...
int ast_cli_register_multiple(struct ast_cli_entry *e, int len)
Register multiple commands.
static struct ast_rtp_glue gtalk_rtp_glue
int ast_setstate(struct ast_channel *chan, enum ast_channel_state)
Change the state of a channel.
int ast_rtp_glue_unregister(struct ast_rtp_glue *glue)
Unregister RTP glue.
Application convenience functions, designed to give consistent look and feel to Asterisk apps...
char * ast_getformatname_multiple(char *buf, size_t size, format_t format)
Get the names of a set of formats.
Data structure associated with a single frame of data.
#define ASTOBJ_CONTAINER_FIND_FULL(container, data, field, hashfunc, hashoffset, comparefunc)
Find an object in a container.
Internal Asterisk hangup causes.
char language[MAX_LANGUAGE]
static int load_module(void)
Load module into PBX, register channel.
Channels have this property if they can accept input with jitter; i.e. most VoIP channels.
void ast_rtp_instance_set_prop(struct ast_rtp_instance *instance, enum ast_rtp_property property, int value)
Set the value of an RTP instance property.
#define ast_sockaddr_to_sin(addr, sin)
Converts a struct ast_sockaddr to a struct sockaddr_in.
enum ast_frame_type frametype
struct ast_variable * next
static format_t gtalk_get_codec(struct ast_channel *chan)
#define ast_mutex_init(pmutex)
#define CONFIG_STATUS_FILEINVALID
static char context[AST_MAX_CONTEXT]
int ast_rtp_instance_dtmf_end_with_duration(struct ast_rtp_instance *instance, char digit, unsigned int duration)
static int gtalk_answer(struct ast_channel *ast)
static int gtalk_action(struct gtalk *client, struct gtalk_pvt *p, const char *action)
static ast_mutex_t gtalklock
#define ASTERISK_GPL_KEY
The text the key() function should return.
#define manager_event(category, event, contents,...)
External routines may send asterisk manager events this way.
Pluggable RTP Architecture.
#define ASTOBJ_REF(object)
Increment an object reference count.
Asterisk module definitions.
static struct hostent * hp
struct gtalk_candidate * next
enum gtalk_protocol protocol
static void gtalk_free_pvt(struct gtalk *client, struct gtalk_pvt *p)
struct gtalk_candidate * theircandidates
static snd_pcm_format_t format
union ast_frame::@172 data
struct ast_channel_tech * tech
struct aji_resource * resources
General jitterbuffer configuration.
void ast_rtp_codecs_payloads_set_m_type(struct ast_rtp_codecs *codecs, struct ast_rtp_instance *instance, int payload)
Record payload information that was seen in an m= SDP line.
char exten[AST_MAX_EXTENSION]
#define AST_MUTEX_DEFINE_STATIC(mutex)
int ast_connect(int sockfd, const struct ast_sockaddr *addr)
Wrapper around connect(2) that uses struct ast_sockaddr.
Structure for mutex and tracking information.
static int gtalk_digit_begin(struct ast_channel *ast, char digit)
void ast_aji_increment_mid(char *mid)
increments the mid field for messages and other events.
int ast_parse_allow_disallow(struct ast_codec_pref *pref, format_t *mask, const char *list, int allowing)
Parse an "allow" or "deny" line in a channel or device configuration and update the capabilities mask...
void ast_rtp_codecs_payload_formats(struct ast_rtp_codecs *codecs, format_t *astformats, int *nonastformats)
Retrieve all formats that were found.
static struct ast_channel * gtalk_request(const char *type, format_t format, const struct ast_channel *requestor, void *data, int *cause)
Part of PBX interface.
struct ast_frame * ast_rtp_instance_read(struct ast_rtp_instance *instance, int rtcp)
Receive a frame over RTP.
#define ASTERISK_FILE_VERSION(file, version)
Register/unregister a source code file with the core.
struct ast_codec_pref prefs
#define ast_mutex_unlock(a)
int ast_sockaddr_resolve(struct ast_sockaddr **addrs, const char *str, int flags, int family)
Parses a string with an IPv4 or IPv6 address and place results into an array.
static int gtalk_add_candidate(struct gtalk *client, ikspak *pak)
static int gtalk_response(struct gtalk *client, char *from, ikspak *pak, const char *reasonstr, const char *reasonstr2)
#define ast_string_field_set(x, field, data)
Set a field to a simple string value.
static int gtalk_get_local_ip(struct ast_sockaddr *ourip)
static struct ast_channel_tech gtalk_tech
PBX interface structure for channel registration.
struct ast_module * ast_module_ref(struct ast_module *)
struct ast_party_number number
Subscriber phone number.
struct aji_client_container * ast_aji_get_clients(void)
struct io_context * io_context_create(void)
Creates a context Create a context for I/O operations Basically mallocs an IO structure and sets up s...