285 #define JABBER_CONFIG "jabber.conf"
298 static void aji_log_hook(
void *data,
const char *xmpp,
size_t size,
int is_incoming);
340 const char *
name,
const char *collection_name);
342 const char *collection_name);
344 const char *collection_name);
346 const char *leaf_name);
352 const char *device_state,
unsigned int cachable);
360 const char* collection_name);
362 const char *
context,
const char *oldmsgs,
const char *newmsgs);
366 const char *event_type,
unsigned int cachable);
415 iks_filter_delete(obj->
f);
416 iks_parser_delete(obj->
p);
417 iks_stack_delete(obj->
stack);
480 node = pak->from->full;
483 version =
"none supplied.";
486 if (!strcasecmp(list->
node, node)) {
489 if (!strcasecmp(res->
version, version)) {
547 if (!buddy || !name) {
552 if (!strcasecmp(res->
resource, name)) {
568 if (iks_find_with_attrib(node,
"c",
"node",
"http://www.google.com/xmpp/client/caps")) {
569 ast_debug(1,
"Found resource with Googletalk voice capabilities\n");
571 }
else if (iks_find_with_attrib(node,
"caps:c",
"ext",
"pmuc-v1 sms-v1 camera-v1 video-v1 voice-v1")) {
572 ast_debug(1,
"Found resource with Gmail voice/video chat capabilities\n");
574 }
else if (iks_find_with_attrib(node,
"caps:c",
"ext",
"pmuc-v1 sms-v1 video-v1 voice-v1")) {
575 ast_debug(1,
"Found resource with Gmail voice/video chat capabilities (no camera)\n");
594 iks_insert_attrib(x,
"type",
"set");
595 y = iks_insert(x,
"query");
596 iks_insert_attrib(y,
"xmlns", IKS_NS_AUTH);
597 iks_insert_cdata(iks_insert(y,
"username"), id->user, 0);
598 iks_insert_cdata(iks_insert(y,
"resource"), id->resource, 0);
602 snprintf(sidpass,
sizeof(sidpass),
"%s%s", sid, pass);
604 iks_insert_cdata(iks_insert(y,
"digest"), buf, 0);
606 iks_insert_cdata(iks_insert(y,
"password"), pass, 0);
628 static int deprecation_warning = 0;
639 if (deprecation_warning++ % 10 == 0) {
640 ast_log(
LOG_WARNING,
"JabberStatus is deprecated. Please use the JABBER_STATUS dialplan function in the future.\n");
644 ast_log(
LOG_ERROR,
"Usage: JabberStatus(<sender>,<jid>[/<resource>],<varname>\n");
650 if (
args.argc != 3) {
656 if (jid.argc < 1 || jid.argc > 2) {
678 ast_log(
LOG_NOTICE,
"Resource '%s' of buddy '%s' was not found\n", jid.resource, jid.screenname);
682 snprintf(status,
sizeof(status),
"%d", stat);
717 if (
args.argc != 2) {
718 ast_log(
LOG_ERROR,
"JABBER_STATUS requires 2 arguments: sender and jid.\n");
723 if (jid.argc < 1 || jid.argc > 2) {
745 ast_log(
LOG_NOTICE,
"Resource %s of buddy %s was not found.\n", jid.resource, jid.screenname);
749 snprintf(buf, buflen,
"%d", stat);
754 .
name =
"JABBER_STATUS",
771 int jidlen, resourcelen;
772 struct timeval start;
795 if (
args.argc < 2 ||
args.argc > 3) {
810 sscanf(
args.timeout,
"%d", &timeout);
817 jidlen = strlen(jid.screenname);
818 resourcelen =
ast_strlen_zero(jid.resource) ? 0 : strlen(jid.resource);
826 ast_debug(3,
"Waiting for an XMPP message from %s\n",
args.jid);
838 while (diff < timeout) {
839 struct timespec ts = { 0, };
844 ts.tv_sec = wait.tv_sec;
845 ts.tv_nsec = wait.tv_usec * 1000;
851 if (res == ETIMEDOUT) {
852 ast_debug(3,
"No message received from %s in %d seconds\n",
args.jid, timeout);
860 if (strncasecmp(jid.screenname, tmp->
from, jidlen)) {
865 char *resource = strchr(tmp->
from,
'/');
866 if (!resource || strlen(resource) == 0) {
868 if (strncasecmp(jid.screenname, tmp->
from, jidlen)) {
873 if (strncasecmp(jid.screenname, tmp->
from, jidlen) || strncmp(jid.resource, resource, resourcelen)) {
880 ast_debug(3,
"Found old message from %s, deleting it\n", tmp->
from);
916 .
name =
"JABBER_RECEIVE",
948 if (!from || !strncasecmp(from, tmp->
from, strlen(from))) {
955 if (!from || !strncasecmp(from, tmp->
from, strlen(from))) {
1001 ast_log(
LOG_ERROR,
"%s requires arguments (sender,jid[,nickname])\n", app_ajijoin);
1007 if (
args.argc < 2 ||
args.argc > 3) {
1008 ast_log(
LOG_ERROR,
"%s requires arguments (sender,jid[,nickname])\n", app_ajijoin);
1012 if (strchr(
args.jid,
'/')) {
1026 sprintf(nick,
"asterisk");
1061 ast_log(
LOG_ERROR,
"%s requires arguments (sender,jid[,nickname])\n", app_ajileave);
1067 if (
args.argc < 2 ||
args.argc > 3) {
1068 ast_log(
LOG_ERROR,
"%s requires arguments (sender,jid[,nickname])\n", app_ajileave);
1072 if (strchr(
args.jid,
'/')) {
1086 sprintf(nick,
"asterisk");
1124 if (
args.argc < 3) {
1161 ast_log(
LOG_ERROR,
"%s requires arguments (sender,groupchatid,message[,nickname])\n", app_ajisendgroup);
1167 if (
args.argc < 3 ||
args.argc > 4) {
1168 ast_log(
LOG_ERROR,
"%s requires arguments (sender,groupchatid,message[,nickname])\n", app_ajisendgroup);
1179 sprintf(nick,
"asterisk");
1192 if (res != IKS_OK) {
1225 if ((ret = iks_send_raw(client->
p,
"<starttls xmlns='urn:ietf:params:xml:ns:xmpp-tls'/>"))) {
1245 ast_debug(1,
"Starting TLS handshake\n");
1250 return IKS_NET_TLSFAIL;
1252 ssl_opts = SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3;
1253 SSL_CTX_set_options(client->
ssl_context, ssl_opts);
1257 return IKS_NET_TLSFAIL;
1261 sock = iks_fd(client->
p);
1262 if (!(ret = SSL_set_fd(client->
ssl_session, sock))) {
1263 return IKS_NET_TLSFAIL;
1268 return IKS_NET_TLSFAIL;
1276 return IKS_NET_TLSFAIL;
1279 ast_debug(1,
"TLS started with server\n");
1298 struct pollfd pfd = { .events = POLLIN };
1309 pfd.fd = iks_fd(client->
p);
1311 res =
ast_poll(&pfd, 1, timeout > 0 ? timeout * 1000 : -1);
1315 len = SSL_read(client->
ssl_session, buffer, buf_len);
1318 len = recv(pfd.fd, buffer, buf_len, 0);
1322 }
else if (len <= 0) {
1350 memset(buf, 0,
sizeof(buf));
1351 memset(newbuf, 0,
sizeof(newbuf));
1355 if (len < 0)
return IKS_NET_RWERR;
1367 while (isspace(buf[pos+1])) {
1371 newbuf[newbufpos] = c;
1384 ret = iks_parse(client->
p, newbuf, 0, 0);
1385 memset(newbuf, 0,
sizeof(newbuf));
1398 if (ret != IKS_OK) {
1401 ast_debug(3,
"XML parsing successful\n");
1418 len = 91 + strlen(client->
name_space) + 6 + strlen(to) + 16 + 1;
1419 msg = iks_malloc(len);
1422 sprintf(msg,
"<?xml version='1.0'?>"
1423 "<stream:stream xmlns:stream='http://etherx.jabber.org/streams' xmlns='"
1424 "%s' to='%s' version='1.0'>", client->
name_space, to);
1441 return aji_send_raw(client, iks_string(iks_stack(x), x));
1457 int len = strlen(xmlstr);
1460 ret = SSL_write(client->
ssl_session, xmlstr, len);
1471 ret = iks_send_raw(client->
p, xmlstr);
1472 if (ret != IKS_OK) {
1487 static void aji_log_hook(
void *data,
const char *xmpp,
size_t size,
int is_incoming)
1495 if (client->
debug) {
1499 if (strlen(xmpp) == 1) {
1533 return iks_start_sasl(client->
p, IKS_SASL_DIGEST_MD5, username, pass);
1534 if (!(type & IKS_STREAM_SASL_PLAIN)) {
1536 return IKS_NET_NOTSUPP;
1539 x = iks_new(
"auth");
1542 return IKS_NET_NOTSUPP;
1545 iks_insert_attrib(x,
"xmlns", IKS_NS_XMPP_SASL);
1546 len = strlen(username) + strlen(pass) + 3;
1549 iks_insert_attrib(x,
"mechanism",
"PLAIN");
1550 snprintf(s, len,
"%c%s%c%s", 0, username, 0, pass);
1556 ast_base64encode(base64, (
const unsigned char *) s, len - 1, (len + 2) * 4 / 3);
1557 iks_insert_cdata(x, base64, 0);
1590 pak = iks_packet(node);
1595 if (iks_has_children(node) && strchr(iks_name(iks_child(node)),
':')) {
1596 char *node_ns = NULL;
1598 char *node_name = iks_name(iks_child(node));
1599 char *aux = strchr(node_name,
':') + 1;
1600 snprintf(attr, strlen(
"xmlns:") + (strlen(node_name) - strlen(aux)),
"xmlns:%s", node_name);
1601 node_ns = iks_find_attrib(iks_child(node), attr);
1604 pak->query = iks_child(node);
1611 case IKS_NODE_START:
1613 #ifndef HAVE_OPENSSL
1614 ast_log(
LOG_ERROR,
"TLS connection cannot be established. Please install OpenSSL and its development libraries on this system, or disable the TLS option in your configuration file\n");
1627 iks_filter_add_rule(client->
f,
aji_client_connect, client, IKS_RULE_TYPE, IKS_PAK_IQ, IKS_RULE_SUBTYPE, IKS_TYPE_RESULT, IKS_RULE_ID, client->
mid, IKS_RULE_DONE);
1630 iks_insert_attrib(auth,
"id", client->
mid);
1631 iks_insert_attrib(auth,
"to", client->
jid->server);
1641 case IKS_NODE_NORMAL:
1644 if (!strcmp(
"proceed", iks_name(node))) {
1649 if (!strcmp(
"stream:features", iks_name(node))) {
1650 features = iks_stream_features(node);
1656 if (features & IKS_STREAM_BIND) {
1657 iks_filter_add_rule(client->
f,
aji_client_connect, client, IKS_RULE_TYPE, IKS_PAK_IQ, IKS_RULE_SUBTYPE, IKS_TYPE_RESULT, IKS_RULE_DONE);
1658 auth = iks_make_resource_bind(client->
jid);
1660 iks_insert_attrib(auth,
"id", client->
mid);
1669 if (features & IKS_STREAM_SESSION) {
1670 iks_filter_add_rule (client->
f,
aji_client_connect, client, IKS_RULE_TYPE, IKS_PAK_IQ, IKS_RULE_SUBTYPE, IKS_TYPE_RESULT, IKS_RULE_ID,
"auth", IKS_RULE_DONE);
1671 auth = iks_make_session();
1673 iks_insert_attrib(auth,
"id",
"auth");
1683 if (!client->
jid->user) {
1689 if (ret != IKS_OK) {
1696 }
else if (!strcmp(
"failure", iks_name(node))) {
1697 ast_log(
LOG_ERROR,
"JABBER: encryption failure. possible bad password.\n");
1698 }
else if (!strcmp(
"success", iks_name(node))) {
1703 case IKS_NODE_ERROR:
1716 case IKS_NODE_START:
1718 char secret[160], shasum[320], *handshake;
1720 sprintf(secret,
"%s%s", pak->id, client->
password);
1722 if (
ast_asprintf(&handshake,
"<handshake>%s</handshake>", shasum) >= 0) {
1735 case IKS_NODE_NORMAL:
1738 case IKS_NODE_ERROR:
1750 switch (pak->type) {
1752 ast_debug(1,
"JABBER: I don't know what to do with paktype NONE.\n");
1754 case IKS_PAK_MESSAGE:
1756 ast_debug(1,
"JABBER: Handling paktype MESSAGE.\n");
1758 case IKS_PAK_PRESENCE:
1760 ast_debug(1,
"JABBER: Handling paktype PRESENCE\n");
1764 ast_debug(1,
"JABBER: Handling paktype S10N\n");
1767 ast_debug(1,
"JABBER: Handling paktype IQ\n");
1771 ast_debug(1,
"JABBER: I don't know anything about paktype '%u'\n", pak->type);
1775 iks_filter_packet(client->
f, pak);
1793 iks *iq = NULL, *presence = NULL, *x = NULL;
1796 presence = iks_new(
"presence");
1798 if (client && iq && presence && x) {
1799 if (!iks_find(pak->query,
"remove")) {
1800 iks_insert_attrib(iq,
"from", client->
jid->full);
1801 iks_insert_attrib(iq,
"to", pak->from->full);
1802 iks_insert_attrib(iq,
"id", pak->id);
1803 iks_insert_attrib(iq,
"type",
"result");
1806 iks_insert_attrib(presence,
"from", client->
jid->full);
1807 iks_insert_attrib(presence,
"to", pak->from->partial);
1808 iks_insert_attrib(presence,
"id", client->
mid);
1810 iks_insert_attrib(presence,
"type",
"subscribe");
1811 iks_insert_attrib(x,
"xmlns",
"vcard-temp:x:update");
1812 iks_insert_node(presence, x);
1820 iks_delete(presence);
1824 return IKS_FILTER_EAT;
1838 iks *iq = NULL, *query = NULL;
1844 iks *error = NULL, *notacceptable = NULL;
1846 ast_log(
LOG_ERROR,
"Someone.... %s tried to register but they aren't allowed\n", pak->from->partial);
1848 query = iks_new(
"query");
1849 error = iks_new(
"error");
1850 notacceptable = iks_new(
"not-acceptable");
1851 if (iq && query && error && notacceptable) {
1852 iks_insert_attrib(iq,
"type",
"error");
1853 iks_insert_attrib(iq,
"from", client->
user);
1854 iks_insert_attrib(iq,
"to", pak->from->full);
1855 iks_insert_attrib(iq,
"id", pak->id);
1856 iks_insert_attrib(query,
"xmlns",
"jabber:iq:register");
1857 iks_insert_attrib(error,
"code" ,
"406");
1858 iks_insert_attrib(error,
"type",
"modify");
1859 iks_insert_attrib(notacceptable,
"xmlns",
"urn:ietf:params:xml:ns:xmpp-stanzas");
1860 iks_insert_node(iq, query);
1861 iks_insert_node(iq, error);
1862 iks_insert_node(error, notacceptable);
1869 iks_delete(notacceptable);
1870 }
else if (!(node = iks_find_attrib(pak->query,
"node"))) {
1871 iks *instructions = NULL;
1872 char *explain =
"Welcome to Asterisk - the Open Source PBX.\n";
1874 query = iks_new(
"query");
1875 instructions = iks_new(
"instructions");
1876 if (iq && query && instructions && client) {
1877 iks_insert_attrib(iq,
"from", client->
user);
1878 iks_insert_attrib(iq,
"to", pak->from->full);
1879 iks_insert_attrib(iq,
"id", pak->id);
1880 iks_insert_attrib(iq,
"type",
"result");
1881 iks_insert_attrib(query,
"xmlns",
"jabber:iq:register");
1882 iks_insert_cdata(instructions, explain, 0);
1883 iks_insert_node(iq, query);
1884 iks_insert_node(query, instructions);
1890 iks_delete(instructions);
1896 return IKS_FILTER_EAT;
1911 if (!(node = iks_find_attrib(pak->query,
"node"))) {
1912 iks *iq = NULL, *query = NULL, *item = NULL;
1914 query = iks_new(
"query");
1915 item = iks_new(
"item");
1917 if (iq && query && item) {
1918 iks_insert_attrib(iq,
"from", client->
user);
1919 iks_insert_attrib(iq,
"to", pak->from->full);
1920 iks_insert_attrib(iq,
"id", pak->id);
1921 iks_insert_attrib(iq,
"type",
"result");
1922 iks_insert_attrib(query,
"xmlns",
"http://jabber.org/protocol/disco#items");
1923 iks_insert_attrib(item,
"node",
"http://jabber.org/protocol/commands");
1924 iks_insert_attrib(item,
"name",
"Million Dollar Asterisk Commands");
1925 iks_insert_attrib(item,
"jid", client->
user);
1927 iks_insert_node(iq, query);
1928 iks_insert_node(query, item);
1938 }
else if (!strcasecmp(node,
"http://jabber.org/protocol/commands")) {
1939 iks *iq, *query, *confirm;
1941 query = iks_new(
"query");
1942 confirm = iks_new(
"item");
1943 if (iq && query && confirm && client) {
1944 iks_insert_attrib(iq,
"from", client->
user);
1945 iks_insert_attrib(iq,
"to", pak->from->full);
1946 iks_insert_attrib(iq,
"id", pak->id);
1947 iks_insert_attrib(iq,
"type",
"result");
1948 iks_insert_attrib(query,
"xmlns",
"http://jabber.org/protocol/disco#items");
1949 iks_insert_attrib(query,
"node",
"http://jabber.org/protocol/commands");
1950 iks_insert_attrib(confirm,
"node",
"confirmaccount");
1951 iks_insert_attrib(confirm,
"name",
"Confirm AIM account");
1952 iks_insert_attrib(confirm,
"jid",
"blog.astjab.org");
1954 iks_insert_node(iq, query);
1955 iks_insert_node(query, confirm);
1963 iks_delete(confirm);
1965 }
else if (!strcasecmp(node,
"confirmaccount")) {
1966 iks *iq = NULL, *query = NULL, *feature = NULL;
1969 query = iks_new(
"query");
1970 feature = iks_new(
"feature");
1972 if (iq && query && feature && client) {
1973 iks_insert_attrib(iq,
"from", client->
user);
1974 iks_insert_attrib(iq,
"to", pak->from->full);
1975 iks_insert_attrib(iq,
"id", pak->id);
1976 iks_insert_attrib(iq,
"type",
"result");
1977 iks_insert_attrib(query,
"xmlns",
"http://jabber.org/protocol/disco#items");
1978 iks_insert_attrib(feature,
"var",
"http://jabber.org/protocol/commands");
1979 iks_insert_node(iq, query);
1980 iks_insert_node(query, feature);
1988 iks_delete(feature);
1992 return IKS_FILTER_EAT;
2010 ast_log(
LOG_NOTICE,
"JABBER: Received client info from unknown buddy: %s.\n", pak->from->full);
2012 return IKS_FILTER_EAT;
2016 if (pak->subtype == IKS_TYPE_RESULT) {
2018 ast_log(
LOG_NOTICE,
"JABBER: Received client info from %s when not requested.\n", pak->from->full);
2021 return IKS_FILTER_EAT;
2023 if (iks_find_with_attrib(pak->query,
"feature",
"var",
"http://www.google.com/xmpp/protocol/voice/v1")) {
2028 }
else if (pak->subtype == IKS_TYPE_GET) {
2029 iks *iq, *disco, *ident, *google, *query;
2031 query = iks_new(
"query");
2032 ident = iks_new(
"identity");
2033 disco = iks_new(
"feature");
2034 google = iks_new(
"feature");
2035 if (iq && ident && disco && google) {
2036 iks_insert_attrib(iq,
"from", client->
jid->full);
2037 iks_insert_attrib(iq,
"to", pak->from->full);
2038 iks_insert_attrib(iq,
"type",
"result");
2039 iks_insert_attrib(iq,
"id", pak->id);
2040 iks_insert_attrib(query,
"xmlns",
"http://jabber.org/protocol/disco#info");
2041 iks_insert_attrib(ident,
"category",
"client");
2042 iks_insert_attrib(ident,
"type",
"pc");
2043 iks_insert_attrib(ident,
"name",
"asterisk");
2044 iks_insert_attrib(disco,
"var",
"http://jabber.org/protocol/disco#info");
2045 iks_insert_attrib(google,
"var",
"http://www.google.com/xmpp/protocol/voice/v1");
2046 iks_insert_node(iq, query);
2047 iks_insert_node(query, ident);
2048 iks_insert_node(query, google);
2049 iks_insert_node(query, disco);
2060 }
else if (pak->subtype == IKS_TYPE_ERROR) {
2065 return IKS_FILTER_EAT;
2083 ast_log(
LOG_NOTICE,
"JABBER: Received client info from unknown buddy: %s.\n", pak->from->full);
2085 return IKS_FILTER_EAT;
2088 if (pak->subtype == IKS_TYPE_ERROR) {
2091 return IKS_FILTER_EAT;
2094 if (pak->subtype == IKS_TYPE_RESULT) {
2096 ast_log(
LOG_NOTICE,
"JABBER: Received client info from %s when not requested.\n", pak->from->full);
2099 return IKS_FILTER_EAT;
2101 if (iks_find_with_attrib(pak->query,
"feature",
"var",
"http://www.google.com/xmpp/protocol/voice/v1")) {
2106 }
else if (pak->subtype == IKS_TYPE_GET && !(node = iks_find_attrib(pak->query,
"node"))) {
2107 iks *iq, *query, *identity, *disco, *reg, *
commands, *gateway, *
version, *vcard, *search;
2110 query = iks_new(
"query");
2111 identity = iks_new(
"identity");
2112 disco = iks_new(
"feature");
2113 reg = iks_new(
"feature");
2114 commands = iks_new(
"feature");
2115 gateway = iks_new(
"feature");
2116 version = iks_new(
"feature");
2117 vcard = iks_new(
"feature");
2118 search = iks_new(
"feature");
2119 if (iq && query && identity && disco && reg && commands && gateway && version && vcard && search && client) {
2120 iks_insert_attrib(iq,
"from", client->
user);
2121 iks_insert_attrib(iq,
"to", pak->from->full);
2122 iks_insert_attrib(iq,
"id", pak->id);
2123 iks_insert_attrib(iq,
"type",
"result");
2124 iks_insert_attrib(query,
"xmlns",
"http://jabber.org/protocol/disco#info");
2125 iks_insert_attrib(identity,
"category",
"gateway");
2126 iks_insert_attrib(identity,
"type",
"pstn");
2127 iks_insert_attrib(identity,
"name",
"Asterisk The Open Source PBX");
2128 iks_insert_attrib(disco,
"var",
"http://jabber.org/protocol/disco");
2129 iks_insert_attrib(reg,
"var",
"jabber:iq:register");
2130 iks_insert_attrib(commands,
"var",
"http://jabber.org/protocol/commands");
2131 iks_insert_attrib(gateway,
"var",
"jabber:iq:gateway");
2132 iks_insert_attrib(version,
"var",
"jabber:iq:version");
2133 iks_insert_attrib(vcard,
"var",
"vcard-temp");
2134 iks_insert_attrib(search,
"var",
"jabber:iq:search");
2136 iks_insert_node(iq, query);
2137 iks_insert_node(query, identity);
2138 iks_insert_node(query, disco);
2139 iks_insert_node(query, reg);
2140 iks_insert_node(query, commands);
2141 iks_insert_node(query, gateway);
2142 iks_insert_node(query, version);
2143 iks_insert_node(query, vcard);
2144 iks_insert_node(query, search);
2152 iks_delete(identity);
2155 iks_delete(commands);
2156 iks_delete(gateway);
2157 iks_delete(version);
2160 }
else if (pak->subtype == IKS_TYPE_GET && !strcasecmp(node,
"http://jabber.org/protocol/commands")) {
2161 iks *iq, *query, *confirm;
2163 query = iks_new(
"query");
2164 confirm = iks_new(
"item");
2166 if (iq && query && confirm && client) {
2167 iks_insert_attrib(iq,
"from", client->
user);
2168 iks_insert_attrib(iq,
"to", pak->from->full);
2169 iks_insert_attrib(iq,
"id", pak->id);
2170 iks_insert_attrib(iq,
"type",
"result");
2171 iks_insert_attrib(query,
"xmlns",
"http://jabber.org/protocol/disco#items");
2172 iks_insert_attrib(query,
"node",
"http://jabber.org/protocol/commands");
2173 iks_insert_attrib(confirm,
"node",
"confirmaccount");
2174 iks_insert_attrib(confirm,
"name",
"Confirm AIM account");
2175 iks_insert_attrib(confirm,
"jid", client->
user);
2176 iks_insert_node(iq, query);
2177 iks_insert_node(query, confirm);
2185 iks_delete(confirm);
2187 }
else if (pak->subtype == IKS_TYPE_GET && !strcasecmp(node,
"confirmaccount")) {
2188 iks *iq, *query, *feature;
2191 query = iks_new(
"query");
2192 feature = iks_new(
"feature");
2194 if (iq && query && feature && client) {
2195 iks_insert_attrib(iq,
"from", client->
user);
2196 iks_insert_attrib(iq,
"to", pak->from->full);
2197 iks_insert_attrib(iq,
"id", pak->id);
2198 iks_insert_attrib(iq,
"type",
"result");
2199 iks_insert_attrib(query,
"xmlns",
"http://jabber.org/protocol/disco#info");
2200 iks_insert_attrib(feature,
"var",
"http://jabber.org/protocol/commands");
2201 iks_insert_node(iq, query);
2202 iks_insert_node(query, feature);
2210 iks_delete(feature);
2215 return IKS_FILTER_EAT;
2242 ast_debug(3,
"client %s received a message\n", client->
name);
2244 if (!(insert =
ast_calloc(1,
sizeof(*insert)))) {
2255 if (iks_find_cdata(pak->x,
"body")) {
2264 if (!insert->
from) {
2275 ast_debug(3,
"Deleted %d messages for client %s from JID %s\n", deleted, client->
name, pak->from->partial);
2292 char *ver, *node, *descrip, *
type;
2298 if (!buddy && pak->from->partial) {
2300 if (!strcmp((
const char *)pak->from->partial, (
const char *)client->
jid->partial))
2303 ast_log(
LOG_NOTICE,
"Got presence packet from %s, someone not in our roster!!!!\n", pak->from->partial);
2306 type = iks_find_attrib(pak->x,
"type");
2307 if (client->
component && type &&!strcasecmp(
"probe", type)) {
2312 status = (pak->show) ? pak->show : 6;
2313 priority = atoi((iks_find_cdata(pak->x,
"priority")) ? iks_find_cdata(pak->x,
"priority") :
"0");
2315 descrip =
ast_strdup(iks_find_cdata(pak->x,
"status"));
2317 while (tmp && pak->from->
resource) {
2318 if (!strcasecmp(tmp->
resource, pak->from->resource)) {
2326 if (last && found->next) {
2334 }
else if (!found->next) {
2348 if (!last && !found->next) {
2356 last->next = found->next;
2370 if (found->priority > tmp->
priority) {
2399 if (!found && status != 6 && pak->from->resource) {
2408 ast_copy_string(found->resource, pak->from->resource,
sizeof(found->resource));
2410 found->description = descrip;
2416 if (found->priority > tmp->
priority) {
2441 node = iks_find_attrib(iks_find(pak->x,
"c"),
"node");
2442 ver = iks_find_attrib(iks_find(pak->x,
"c"),
"ver");
2445 if (!node && !ver) {
2446 node = iks_find_attrib(iks_find(pak->x,
"caps:c"),
"node");
2447 ver = iks_find_attrib(iks_find(pak->x,
"caps:c"),
"ver");
2451 if (status != 6 && found && !found->cap) {
2454 found->cap->jingle = 1;
2456 if (found->cap->jingle) {
2457 ast_debug(1,
"Special case for google till they support discover.\n");
2461 query = iks_new(
"query");
2463 iks_insert_attrib(iq,
"type",
"get");
2464 iks_insert_attrib(iq,
"to", pak->from->full);
2465 iks_insert_attrib(iq,
"from", client->
jid->full);
2466 iks_insert_attrib(iq,
"id", client->
mid);
2468 iks_insert_attrib(query,
"xmlns",
"http://jabber.org/protocol/disco#info");
2469 iks_insert_node(iq, query);
2478 switch (pak->subtype) {
2479 case IKS_TYPE_AVAILABLE:
2480 ast_debug(3,
"JABBER: I am available ^_* %u\n", pak->subtype);
2482 case IKS_TYPE_UNAVAILABLE:
2483 ast_debug(3,
"JABBER: I am unavailable ^_* %u\n", pak->subtype);
2486 ast_debug(3,
"JABBER: Ohh sexy and the wrong type: %u\n", pak->subtype);
2488 switch (pak->show) {
2489 case IKS_SHOW_UNAVAILABLE:
2490 ast_debug(3,
"JABBER: type: %u subtype %u\n", pak->subtype, pak->show);
2492 case IKS_SHOW_AVAILABLE:
2493 ast_debug(3,
"JABBER: type is available\n");
2496 ast_debug(3,
"JABBER: type: %u subtype %u\n", pak->subtype, pak->show);
2502 ast_debug(3,
"JABBER: type: %u subtype %u\n", pak->subtype, pak->show);
2505 ast_debug(3,
"JABBER: type: %u subtype %u\n", pak->subtype, pak->show);
2508 ast_debug(3,
"JABBER: Kinky! how did that happen %u\n", pak->show);
2513 "Account: %s\r\nJID: %s\r\nResource: %s\r\nStatus: %d\r\nPriority: %d"
2514 "\r\nDescription: %s\r\n",
2515 client->
name, pak->from->partial, found->resource, found->status,
2516 found->priority,
S_OR(found->description,
""));
2519 "Account: %s\r\nJID: %s\r\nStatus: %u\r\n",
2520 client->
name, pak->from->partial, pak->show ? pak->show : IKS_SHOW_UNAVAILABLE);
2533 iks *presence = NULL, *
status = NULL;
2536 switch (pak->subtype) {
2537 case IKS_TYPE_SUBSCRIBE:
2539 presence = iks_new(
"presence");
2540 status = iks_new(
"status");
2541 if (presence && status) {
2542 iks_insert_attrib(presence,
"type",
"subscribed");
2543 iks_insert_attrib(presence,
"to", pak->from->full);
2544 iks_insert_attrib(presence,
"from", client->
jid->full);
2546 iks_insert_attrib(presence,
"id", pak->id);
2547 iks_insert_cdata(status,
"Asterisk has approved subscription", 0);
2548 iks_insert_node(presence, status);
2554 iks_delete(presence);
2560 case IKS_TYPE_SUBSCRIBED:
2562 if (!buddy && pak->from->partial) {
2612 iks *message_packet = NULL;
2626 message_packet = iks_make_msg(groupchat ? IKS_TYPE_GROUPCHAT : IKS_TYPE_CHAT, address, message);
2627 if (!message_packet) {
2631 iks_insert_attrib(message_packet,
"from", from);
2633 iks_delete(message_packet);
2653 iks_insert_attrib(iq,
"type",
"get");
2654 iks_insert_attrib(iq,
"to", server);
2655 iks_insert_attrib(iq,
"id", client->
mid);
2701 iks *invite, *body, *
namespace;
2703 invite = iks_new(
"message");
2704 body = iks_new(
"body");
2705 namespace = iks_new("x");
2706 if (client && invite && body &&
namespace) {
2707 iks_insert_attrib(invite,
"to", user);
2708 iks_insert_attrib(invite,
"id", client->
mid);
2710 iks_insert_cdata(body, message, 0);
2711 iks_insert_attrib(
namespace,
"xmlns",
"jabber:x:conference");
2712 iks_insert_attrib(
namespace,
"jid", room);
2713 iks_insert_node(invite, body);
2714 iks_insert_node(invite,
namespace);
2721 iks_delete(
namespace);
2738 while (res != IKS_OK) {
2745 if (res == IKS_NET_RWERR || client->
timeout == 0) {
2746 while (res != IKS_OK) {
2747 ast_debug(3,
"JABBER: reconnecting.\n");
2756 ast_debug(2,
"Ending our Jabber client's thread due to a disconnect\n");
2766 if (res == IKS_HOOK) {
2768 }
else if (res == IKS_NET_TLSFAIL) {
2772 if (res == IKS_OK) {
2777 }
else if (res == IKS_NET_RWERR) {
2794 for (i = strlen(mid) - 1; i >= 0; i--) {
2795 if (mid[i] !=
'z') {
2796 mid[i] = mid[i] + 1;
2810 static int aji_register_transport(
void *data, ikspak *pak)
2815 iks *send = iks_make_iq(IKS_TYPE_GET,
"jabber:iq:register");
2817 if (client && send) {
2825 iks_filter_remove_hook(client->
f, aji_register_transport);
2826 iks_filter_add_rule(client->
f, aji_register_transport2, client, IKS_RULE_TYPE, IKS_PAK_IQ, IKS_RULE_SUBTYPE, IKS_TYPE_RESULT, IKS_RULE_NS, IKS_NS_REGISTER, IKS_RULE_DONE);
2827 iks_insert_attrib(send,
"to", buddy->host);
2828 iks_insert_attrib(send,
"id", client->
mid);
2830 iks_insert_attrib(send,
"from", client->
user);
2838 return IKS_FILTER_EAT;
2847 static int aji_register_transport2(
void *data, ikspak *pak)
2853 iks *regiq = iks_new(
"iq");
2854 iks *regquery = iks_new(
"query");
2855 iks *reguser = iks_new(
"username");
2856 iks *regpass = iks_new(
"password");
2858 if (client && regquery && reguser && regpass && regiq) {
2864 iks_filter_remove_hook(client->
f, aji_register_transport2);
2865 iks_insert_attrib(regiq,
"to", buddy->host);
2866 iks_insert_attrib(regiq,
"type",
"set");
2867 iks_insert_attrib(regiq,
"id", client->
mid);
2869 iks_insert_attrib(regiq,
"from", client->
user);
2870 iks_insert_attrib(regquery,
"xmlns",
"jabber:iq:register");
2871 iks_insert_cdata(reguser, buddy->user, 0);
2872 iks_insert_cdata(regpass, buddy->pass, 0);
2873 iks_insert_node(regiq, regquery);
2874 iks_insert_node(regquery, reguser);
2875 iks_insert_node(regquery, regpass);
2882 iks_delete(regquery);
2884 iks_delete(reguser);
2886 iks_delete(regpass);
2888 return IKS_FILTER_EAT;
2901 iks *removeiq = iks_new(
"iq");
2902 iks *removequery = iks_new(
"query");
2903 iks *removeitem = iks_new(
"item");
2904 iks *send = iks_make_iq(IKS_TYPE_GET,
"http://jabber.org/protocol/disco#items");
2905 if (!client || !removeiq || !removequery || !removeitem || !send) {
2910 iks_insert_node(removeiq, removequery);
2911 iks_insert_node(removequery, removeitem);
2917 ast_aji_send(client, iks_make_s10n(IKS_TYPE_UNSUBSCRIBE, iterator->name,
2918 "GoodBye. Your status is no longer needed by Asterisk the Open Source PBX"
2919 " so I am no longer subscribing to your presence.\n"));
2920 ast_aji_send(client, iks_make_s10n(IKS_TYPE_UNSUBSCRIBED, iterator->name,
2921 "GoodBye. You are no longer in the Asterisk config file so I am removing"
2922 " your access to my presence.\n"));
2923 iks_insert_attrib(removeiq,
"from", client->
jid->full);
2924 iks_insert_attrib(removeiq,
"type",
"set");
2925 iks_insert_attrib(removequery,
"xmlns",
"jabber:iq:roster");
2926 iks_insert_attrib(removeitem,
"jid", iterator->name);
2927 iks_insert_attrib(removeitem,
"subscription",
"remove");
2930 ast_aji_send(client, iks_make_s10n(IKS_TYPE_SUBSCRIBE, iterator->name,
2931 "Greetings! I am the Asterisk Open Source PBX and I want to subscribe to your presence\n"));
2938 iks_delete(removeiq);
2939 iks_delete(removequery);
2940 iks_delete(removeitem);
2963 x = iks_child(pak->query);
2966 if (!iks_strcmp(iks_name(x),
"item")) {
2967 if (!strcasecmp(iterator->name, iks_find_attrib(x,
"jid"))) {
2982 x = iks_child(pak->query);
2985 if (iks_strcmp(iks_name(x),
"item") == 0) {
2988 if (!strcasecmp(iterator->name, iks_find_attrib(x,
"jid")))
3013 if (!iks_strcmp(iks_find_attrib(x,
"subscription"),
"none") || !iks_strcmp(iks_find_attrib(x,
"subscription"),
"from")) {
3032 return IKS_FILTER_EAT;
3045 if (client->
state) {
3050 iks_parser_reset(client->
p);
3070 roster = iks_make_iq(IKS_TYPE_GET, IKS_NS_ROSTER);
3073 iks_insert_attrib(roster,
"id",
"roster");
3093 int res = IKS_FILTER_PASS;
3097 iks_filter_add_rule(client->
f,
aji_filter_roster, client, IKS_RULE_TYPE, IKS_PAK_IQ, IKS_RULE_SUBTYPE, IKS_TYPE_RESULT, IKS_RULE_ID,
"roster", IKS_RULE_DONE);
3099 client->
jid = (iks_find_cdata(pak->query,
"jid")) ? iks_id_new(client->
stack, iks_find_cdata(pak->query,
"jid")) : client->
jid;
3109 res = IKS_FILTER_EAT;
3136 if (connected == IKS_NET_NOCONN) {
3139 }
else if (connected == IKS_NET_NODNS) {
3156 ast_verb(4,
"JABBER: Disconnecting\n");
3164 iks_disconnect(client->
p);
3165 iks_parser_delete(client->
p);
3195 snprintf(oldmsgs,
sizeof(oldmsgs),
"%u",
3197 snprintf(newmsgs,
sizeof(newmsgs),
"%u",
3212 const char *device_state;
3213 unsigned int cachable;
3241 if (!device_state_sub) {
3253 IKS_PAK_MESSAGE, IKS_RULE_FROM, client->
pubsub_node, IKS_RULE_DONE);
3255 IKS_PAK_IQ, IKS_RULE_SUBTYPE, IKS_TYPE_ERROR, IKS_RULE_DONE);
3266 char *item_id, *device_state, *
mailbox, *cachable_str;
3267 int oldmsgs, newmsgs;
3268 iks *item, *item_content;
3273 item = iks_find(iks_find(iks_find(pak->x,
"event"),
"items"),
"item");
3276 return IKS_FILTER_EAT;
3278 item_id = iks_find_attrib(item,
"id");
3279 item_content = iks_child(item);
3280 ast_str_to_eid(&pubsub_eid, iks_find_attrib(item_content,
"eid"));
3282 ast_log(
LOG_DEBUG,
"Returning here, eid of incoming event matches ours!\n");
3283 return IKS_FILTER_EAT;
3285 if (!strcasecmp(iks_name(item_content),
"state")) {
3286 if ((cachable_str = iks_find_attrib(item_content,
"cachable"))) {
3287 sscanf(cachable_str,
"%30u", &cachable);
3289 device_state = iks_find_cdata(item,
"state");
3296 return IKS_FILTER_EAT;
3298 }
else if (!strcasecmp(iks_name(item_content),
"mailbox")) {
3299 mailbox =
strsep(&item_id,
"@");
3300 sscanf(iks_find_cdata(item_content,
"OLDMSGS"),
"%10d", &oldmsgs);
3301 sscanf(iks_find_cdata(item_content,
"NEWMSGS"),
"%10d", &newmsgs);
3309 return IKS_FILTER_EAT;
3313 iks_name(item_content));
3314 return IKS_FILTER_EAT;
3323 return IKS_FILTER_EAT;
3335 iks *pubsub, *affiliations, *affiliate;
3336 pubsub = iks_insert(modify_affiliates,
"pubsub");
3337 iks_insert_attrib(pubsub,
"xmlns",
"http://jabber.org/protocol/pubsub#owner");
3338 affiliations = iks_insert(pubsub,
"affiliations");
3339 iks_insert_attrib(affiliations,
"node", node);
3342 affiliate = iks_insert(affiliations,
"affiliation");
3343 iks_insert_attrib(affiliate,
"jid", iterator->name);
3344 iks_insert_attrib(affiliate,
"affiliation",
"owner");
3348 iks_delete(modify_affiliates);
3360 iks *pubsub, *subscribe;
3362 pubsub = iks_insert(request,
"pubsub");
3363 iks_insert_attrib(pubsub,
"xmlns",
"http://jabber.org/protocol/pubsub");
3364 subscribe = iks_insert(pubsub,
"subscribe");
3365 iks_insert_attrib(subscribe,
"jid", client->
jid->partial);
3366 iks_insert_attrib(subscribe,
"node", node);
3368 iks *options, *x, *sub_options, *sub_type, *sub_depth;
3369 options = iks_insert(pubsub,
"options");
3370 x = iks_insert(options,
"x");
3371 iks_insert_attrib(x,
"xmlns",
"jabber:x:data");
3372 iks_insert_attrib(x,
"type",
"submit");
3373 sub_options = iks_insert(x,
"field");
3374 iks_insert_attrib(sub_options,
"var",
"FORM_TYPE");
3375 iks_insert_attrib(sub_options,
"type",
"hidden");
3376 iks_insert_cdata(iks_insert(sub_options,
"value"),
3377 "http://jabber.org/protocol/pubsub#subscribe_options", 51);
3378 sub_type = iks_insert(x,
"field");
3379 iks_insert_attrib(sub_type,
"var",
"pubsub#subscription_type");
3380 iks_insert_cdata(iks_insert(sub_type,
"value"),
"items", 5);
3381 sub_depth = iks_insert(x,
"field");
3382 iks_insert_attrib(sub_type,
"var",
"pubsub#subscription_depth");
3383 iks_insert_cdata(iks_insert(sub_depth,
"value"),
"all", 3);
3386 iks_delete(request);
3397 const char *event_type,
unsigned int cachable)
3400 iks *pubsub, *publish, *item;
3401 pubsub = iks_insert(request,
"pubsub");
3402 iks_insert_attrib(pubsub,
"xmlns",
"http://jabber.org/protocol/pubsub");
3403 publish = iks_insert(pubsub,
"publish");
3405 iks_insert_attrib(publish,
"node", node);
3407 iks_insert_attrib(publish,
"node", event_type);
3409 item = iks_insert(publish,
"item");
3410 iks_insert_attrib(item,
"id", node);
3413 iks *options, *x, *field_form_type, *field_persist;
3415 options = iks_insert(pubsub,
"publish-options");
3416 x = iks_insert(options,
"x");
3417 iks_insert_attrib(x,
"xmlns",
"jabber:x:data");
3418 iks_insert_attrib(x,
"type",
"submit");
3419 field_form_type = iks_insert(x,
"field");
3420 iks_insert_attrib(field_form_type,
"var",
"FORM_TYPE");
3421 iks_insert_attrib(field_form_type,
"type",
"hidden");
3422 iks_insert_cdata(iks_insert(field_form_type,
"value"),
"http://jabber.org/protocol/pubsub#publish-options", 0);
3423 field_persist = iks_insert(x,
"field");
3424 iks_insert_attrib(field_persist,
"var",
"pubsub#persist_items");
3425 iks_insert_cdata(iks_insert(field_persist,
"value"),
"0", 1);
3439 const char *device_state,
unsigned int cachable)
3443 char eid_str[20], cachable_str[2];
3452 state = iks_insert(request,
"state");
3453 iks_insert_attrib(state,
"xmlns",
"http://asterisk.org");
3454 iks_insert_attrib(state,
"eid", eid_str);
3455 snprintf(cachable_str,
sizeof(cachable_str),
"%u", cachable);
3456 iks_insert_attrib(state,
"cachable", cachable_str);
3457 iks_insert_cdata(state, device_state, strlen(device_state));
3459 iks_delete(request);
3470 const char *
context,
const char *oldmsgs,
const char *newmsgs)
3474 iks *mailbox_node, *request;
3475 snprintf(full_mailbox,
sizeof(full_mailbox),
"%s@%s", mailbox, context);
3478 mailbox_node = iks_insert(request,
"mailbox");
3479 iks_insert_attrib(mailbox_node,
"xmlns",
"http://asterisk.org");
3480 iks_insert_attrib(mailbox_node,
"eid", eid_str);
3481 iks_insert_cdata(iks_insert(mailbox_node,
"NEWMSGS"), newmsgs, strlen(newmsgs));
3482 iks_insert_cdata(iks_insert(mailbox_node,
"OLDMSGS"), oldmsgs, strlen(oldmsgs));
3484 iks_delete(request);
3495 iks *request = iks_new(
"iq");
3497 iks_insert_attrib(request,
"to", client->
pubsub_node);
3498 iks_insert_attrib(request,
"from", client->
jid->full);
3499 iks_insert_attrib(request,
"type", type);
3501 iks_insert_attrib(request,
"id", client->
mid);
3511 iks *orig_pubsub = iks_find(pak->x,
"pubsub");
3514 ast_debug(1,
"Error isn't a PubSub error, why are we here?\n");
3515 return IKS_FILTER_EAT;
3517 orig_request = iks_child(orig_pubsub);
3518 error = iks_find_attrib(iks_find(pak->x,
"error"),
"code");
3519 node_name = iks_find_attrib(orig_request,
"node");
3520 if (!sscanf(error,
"%30d", &error_num)) {
3521 return IKS_FILTER_EAT;
3523 if (error_num > 399 && error_num < 500 && error_num != 404) {
3525 "Error performing operation on PubSub node %s, %s.\n", node_name, error);
3526 return IKS_FILTER_EAT;
3527 }
else if (error_num > 499 && error_num < 600) {
3529 return IKS_FILTER_EAT;
3534 if (!strcasecmp(iks_name(orig_request),
"publish")) {
3537 if (iks_find(iks_find(orig_request,
"item"),
"state")) {
3539 }
else if (iks_find(iks_find(orig_request,
"item"),
"mailbox")) {
3546 iks_insert_node(request, orig_pubsub);
3548 iks_delete(request);
3550 return IKS_FILTER_EAT;
3551 }
else if (!strcasecmp(iks_name(orig_request),
"subscribe")) {
3559 return IKS_FILTER_EAT;
3573 IKS_PAK_IQ, IKS_RULE_SUBTYPE, IKS_TYPE_RESULT, IKS_RULE_ID, client->
mid,
3576 iks_delete(request);
3590 query = iks_insert(request,
"query");
3591 iks_insert_attrib(query,
"xmlns",
"http://jabber.org/protocol/disco#items");
3593 iks_insert_attrib(query,
"node", collection);
3609 if (iks_has_children(pak->query)) {
3610 item = iks_first_tag(pak->query);
3611 ast_verbose(
"Connection %s: %s\nNode name: %s\n", client->
name, client->
jid->partial,
3612 iks_find_attrib(item,
"node"));
3613 while ((item = iks_next_tag(item))) {
3614 ast_verbose(
"Node name: %s\n", iks_find_attrib(item,
"node"));
3621 return IKS_FILTER_EAT;
3636 const char *
name = NULL;
3637 const char *collection = NULL;
3641 e->
command =
"jabber list nodes";
3643 "Usage: jabber list nodes <connection> [collection]\n"
3644 " Lists the user's nodes on the respective connection\n"
3645 " ([connection] as configured in jabber.conf.)\n";
3653 }
else if (a->
argc == 4 || a->
argc == 5) {
3657 collection = a->
argv[4];
3660 ast_cli(a->
fd,
"Unable to find client '%s'!\n", name);
3664 ast_cli(a->
fd,
"Listing pubsub nodes.\n");
3685 e->
command =
"jabber purge nodes";
3687 "Usage: jabber purge nodes <connection> <node>\n"
3688 " Purges nodes on PubSub server\n"
3689 " as configured in jabber.conf.\n";
3701 ast_cli(a->
fd,
"Unable to find client '%s'!\n", name);
3718 IKS_PAK_IQ, IKS_RULE_SUBTYPE, IKS_TYPE_RESULT, IKS_RULE_ID, client->
mid,
3721 iks_delete(request);
3735 if (iks_has_children(pak->query)) {
3736 item = iks_first_tag(pak->query);
3738 iks_find_attrib(item,
"node"));
3739 while ((item = iks_next_tag(item))) {
3746 return IKS_FILTER_EAT;
3765 e->
command =
"jabber delete node";
3767 "Usage: jabber delete node <connection> <node>\n"
3768 " Deletes a node on PubSub server\n"
3769 " as configured in jabber.conf.\n";
3781 ast_cli(a->
fd,
"Unable to find client '%s'!\n", name);
3798 iks *pubsub, *
delete;
3799 pubsub = iks_insert(request,
"pubsub");
3800 iks_insert_attrib(pubsub,
"xmlns",
"http://jabber.org/protocol/pubsub#owner");
3801 delete = iks_insert(pubsub,
"delete");
3802 iks_insert_attrib(
delete,
"node", node_name);
3826 const char *leaf_name)
3839 char *
name,
const char *collection_name)
3842 iks *pubsub, *create;
3843 pubsub = iks_insert(node,
"pubsub");
3844 iks_insert_attrib(pubsub,
"xmlns",
"http://jabber.org/protocol/pubsub");
3845 create = iks_insert(pubsub,
"create");
3846 iks_insert_attrib(create,
"node", name);
3858 iks *configure, *x, *field_owner, *field_node_type, *field_node_config,
3859 *field_deliver_payload, *field_persist_items, *field_access_model,
3860 *field_pubsub_collection;
3861 configure = iks_insert(pubsub,
"configure");
3862 x = iks_insert(configure,
"x");
3863 iks_insert_attrib(x,
"xmlns",
"jabber:x:data");
3864 iks_insert_attrib(x,
"type",
"submit");
3865 field_owner = iks_insert(x,
"field");
3866 iks_insert_attrib(field_owner,
"var",
"FORM_TYPE");
3867 iks_insert_attrib(field_owner,
"type",
"hidden");
3868 iks_insert_cdata(iks_insert(field_owner,
"value"),
3869 "http://jabber.org/protocol/pubsub#owner", 39);
3871 field_node_type = iks_insert(x,
"field");
3872 iks_insert_attrib(field_node_type,
"var",
"pubsub#node_type");
3873 iks_insert_cdata(iks_insert(field_node_type,
"value"), node_type, strlen(node_type));
3875 field_node_config = iks_insert(x,
"field");
3876 iks_insert_attrib(field_node_config,
"var",
"FORM_TYPE");
3877 iks_insert_attrib(field_node_config,
"type",
"hidden");
3878 iks_insert_cdata(iks_insert(field_node_config,
"value"),
3879 "http://jabber.org/protocol/pubsub#node_config", 45);
3880 field_deliver_payload = iks_insert(x,
"field");
3881 iks_insert_attrib(field_deliver_payload,
"var",
"pubsub#deliver_payloads");
3882 iks_insert_cdata(iks_insert(field_deliver_payload,
"value"),
"1", 1);
3883 field_persist_items = iks_insert(x,
"field");
3884 iks_insert_attrib(field_persist_items,
"var",
"pubsub#persist_items");
3885 iks_insert_cdata(iks_insert(field_persist_items,
"value"),
"1", 1);
3886 field_access_model = iks_insert(x,
"field");
3887 iks_insert_attrib(field_access_model,
"var",
"pubsub#access_model");
3888 iks_insert_cdata(iks_insert(field_access_model,
"value"),
"whitelist", 9);
3889 if (node_type && !strcasecmp(node_type,
"leaf")) {
3890 field_pubsub_collection = iks_insert(x,
"field");
3891 iks_insert_attrib(field_pubsub_collection,
"var",
"pubsub#collection");
3892 iks_insert_cdata(iks_insert(field_pubsub_collection,
"value"), collection_name,
3893 strlen(collection_name));
3908 const char *collection_name;
3912 e->
command =
"jabber create collection";
3914 "Usage: jabber create collection <connection> <collection>\n"
3915 " Creates a PubSub collection node using the account\n"
3916 " as configured in jabber.conf.\n";
3926 collection_name = a->
argv[4];
3929 ast_cli(a->
fd,
"Unable to find client '%s'!\n", name);
3933 ast_cli(a->
fd,
"Creating test PubSub node collection.\n");
3947 const char *collection_name;
3948 const char *leaf_name;
3952 e->
command =
"jabber create leaf";
3954 "Usage: jabber create leaf <connection> <collection> <leaf>\n"
3955 " Creates a PubSub leaf node using the account\n"
3956 " as configured in jabber.conf.\n";
3966 collection_name = a->
argv[4];
3967 leaf_name = a->
argv[5];
3970 ast_cli(a->
fd,
"Unable to find client '%s'!\n", name);
3974 ast_cli(a->
fd,
"Creating test PubSub node collection.\n");
3994 iks *presence = iks_make_pres(level, desc);
3995 iks *cnode = iks_new(
"c");
3996 iks *
priority = iks_new(
"priority");
3999 if (presence && cnode && client && priority) {
4001 iks_insert_attrib(presence,
"to", to);
4004 iks_insert_attrib(presence,
"from", from);
4006 snprintf(priorityS,
sizeof(priorityS),
"%d", client->
priority);
4007 iks_insert_cdata(priority, priorityS, strlen(priorityS));
4008 iks_insert_node(presence, priority);
4009 iks_insert_attrib(cnode,
"node",
"http://www.asterisk.org/xmpp/client/caps");
4010 iks_insert_attrib(cnode,
"ver",
"asterisk-xmpp");
4011 iks_insert_attrib(cnode,
"ext",
"voice-v1");
4012 iks_insert_attrib(cnode,
"xmlns",
"http://jabber.org/protocol/caps");
4013 iks_insert_node(presence, cnode);
4020 iks_delete(presence);
4021 iks_delete(priority);
4037 iks *presence = NULL, *x = NULL;
4041 presence = iks_make_pres(level, NULL);
4049 snprintf(roomid,
AJI_MAX_JIDLEN,
"%s/%s", room, nick ? nick : client->
jid->user);
4052 if (!presence || !x || !client) {
4057 iks_insert_attrib(presence,
"to", roomid);
4058 iks_insert_attrib(presence,
"from", from);
4059 iks_insert_attrib(x,
"xmlns",
MUC_NS);
4060 iks_insert_node(presence, x);
4065 iks_delete(presence);
4079 e->
command =
"jabber set debug {on|off}";
4081 "Usage: jabber set debug {on|off}\n"
4082 " Enables/disables dumping of XMPP/Jabber packets for debugging purposes.\n";
4092 if (!strncasecmp(a->
argv[e->
args - 1],
"on", 2)) {
4095 iterator->debug = 1;
4098 ast_cli(a->
fd,
"Jabber Debugging Enabled.\n");
4100 }
else if (!strncasecmp(a->
argv[e->
args - 1],
"off", 3)) {
4103 iterator->debug = 0;
4106 ast_cli(a->
fd,
"Jabber Debugging Disabled.\n");
4123 "Usage: jabber reload\n"
4124 " Reloads the Jabber module.\n";
4147 e->
command =
"jabber show connections";
4149 "Usage: jabber show connections\n"
4150 " Shows state of client and component connections\n";
4156 ast_cli(a->
fd,
"Jabber Users and their status:\n");
4160 switch (iterator->state) {
4162 status =
"Disconnected";
4165 status =
"Connecting";
4168 status =
"Connected";
4173 ast_cli(a->
fd,
" [%s] %s - %s\n", iterator->name, iterator->user, status);
4177 ast_cli(a->
fd,
" Number of users: %d\n", count);
4193 e->
command =
"jabber show buddies";
4195 "Usage: jabber show buddies\n"
4196 " Shows buddy lists of our clients\n";
4204 ast_cli(a->
fd,
"Client: %s\n", iterator->user);
4208 ast_cli(a->
fd,
"\tBuddy:\t%s\n", iterator->name);
4209 if (!iterator->resources)
4211 for (resource = iterator->resources; resource; resource = resource->
next) {
4213 if (resource->
cap) {
4264 client->
port = 5222;
4276 client->
status = IKS_SHOW_AVAILABLE;
4283 if (!strcasecmp(var->
name,
"username")) {
4285 }
else if (!strcasecmp(var->
name,
"serverhost")) {
4287 }
else if (!strcasecmp(var->
name,
"secret")) {
4289 }
else if (!strcasecmp(var->
name,
"statusmessage")) {
4291 }
else if (!strcasecmp(var->
name,
"port")) {
4293 }
else if (!strcasecmp(var->
name,
"timeout")) {
4295 }
else if (!strcasecmp(var->
name,
"debug")) {
4297 }
else if (!strcasecmp(var->
name,
"type")) {
4298 if (!strcasecmp(var->
value,
"component")) {
4301 ast_log(
LOG_ERROR,
"Client cannot be configured to be both a component and to distribute events! Event distribution will be disabled.\n");
4305 }
else if (!strcasecmp(var->
name,
"distribute_events")) {
4308 ast_log(
LOG_ERROR,
"Client cannot be configured to be both a component and to distribute events! Event distribution will be disabled.\n");
4311 ast_log(
LOG_ERROR,
"Only one connection can be configured for distributed events.\n");
4318 }
else if (!strcasecmp(var->
name,
"pubsub_node")) {
4320 }
else if (!strcasecmp(var->
name,
"usetls")) {
4322 }
else if (!strcasecmp(var->
name,
"usesasl")) {
4324 }
else if (!strcasecmp(var->
name,
"forceoldssl")) {
4326 }
else if (!strcasecmp(var->
name,
"keepalive")) {
4328 }
else if (!strcasecmp(var->
name,
"autoprune")) {
4330 }
else if (!strcasecmp(var->
name,
"autoregister")) {
4332 }
else if (!strcasecmp(var->
name,
"auth_policy")) {
4333 if (!strcasecmp(var->
value,
"accept")) {
4338 }
else if (!strcasecmp(var->
name,
"buddy")) {
4340 }
else if (!strcasecmp(var->
name,
"priority")) {
4342 }
else if (!strcasecmp(var->
name,
"status")) {
4343 if (!strcasecmp(var->
value,
"unavailable")) {
4344 client->
status = IKS_SHOW_UNAVAILABLE;
4345 }
else if (!strcasecmp(var->
value,
"available")
4346 || !strcasecmp(var->
value,
"online")) {
4347 client->
status = IKS_SHOW_AVAILABLE;
4348 }
else if (!strcasecmp(var->
value,
"chat")
4349 || !strcasecmp(var->
value,
"chatty")) {
4350 client->
status = IKS_SHOW_CHAT;
4351 }
else if (!strcasecmp(var->
value,
"away")) {
4352 client->
status = IKS_SHOW_AWAY;
4353 }
else if (!strcasecmp(var->
value,
"xa")
4354 || !strcasecmp(var->
value,
"xaway")) {
4355 client->
status = IKS_SHOW_XA;
4356 }
else if (!strcasecmp(var->
value,
"dnd")) {
4357 client->
status = IKS_SHOW_DND;
4358 }
else if (!strcasecmp(var->
value,
"invisible")) {
4359 #ifdef IKS_SHOW_INVISIBLE
4360 client->
status = IKS_SHOW_INVISIBLE;
4362 ast_log(
LOG_WARNING,
"Your iksemel doesn't support invisible status: falling back to DND\n");
4363 client->
status = IKS_SHOW_DND;
4387 client->
stack = iks_stack_new(8192, 8192);
4388 if (!client->
stack) {
4392 client->
f = iks_filter_new();
4399 client->
jid = iks_id_new(client->
stack, resource);
4406 iks_filter_add_rule(client->
f,
aji_dinfo_handler, client, IKS_RULE_NS,
"http://jabber.org/protocol/disco#info", IKS_RULE_DONE);
4407 iks_filter_add_rule(client->
f,
aji_ditems_handler, client, IKS_RULE_NS,
"http://jabber.org/protocol/disco#items", IKS_RULE_DONE);
4408 iks_filter_add_rule(client->
f,
aji_register_query_handler, client, IKS_RULE_SUBTYPE, IKS_TYPE_GET, IKS_RULE_NS,
"jabber:iq:register", IKS_RULE_DONE);
4409 iks_filter_add_rule(client->
f,
aji_register_approve_handler, client, IKS_RULE_SUBTYPE, IKS_TYPE_SET, IKS_RULE_NS,
"jabber:iq:register", IKS_RULE_DONE);
4411 iks_filter_add_rule(client->
f,
aji_client_info_handler, client, IKS_RULE_NS,
"http://jabber.org/protocol/disco#info", IKS_RULE_DONE);
4429 static int aji_create_transport(
char *label,
struct aji_client *client)
4431 char *server = NULL, *buddyname = NULL, *
user = NULL, *
pass = NULL;
4433 int needs_unref = 1;
4447 if ((buddyname = strchr(label,
','))) {
4450 if (buddyname && buddyname[0] !=
'\0') {
4451 if ((user = strchr(buddyname,
','))) {
4454 if (user && user[0] !=
'\0') {
4455 if ((pass = strchr(user,
','))) {
4493 int needs_unref = 1;
4539 if (!strcasecmp(var->
name,
"debug")) {
4541 }
else if (!strcasecmp(var->
name,
"autoprune")) {
4543 }
else if (!strcasecmp(var->
name,
"autoregister")) {
4545 }
else if (!strcasecmp(var->
name,
"collection_nodes")) {
4547 }
else if (!strcasecmp(var->
name,
"pubsub_autocreate")) {
4549 }
else if (!strcasecmp(var->
name,
"auth_policy")) {
4550 if (!strcasecmp(var->
value,
"accept")) {
4559 if (strcasecmp(cat,
"general")) {
4581 if (!client && strchr(name,
'@')) {
4584 if (strchr(aux,
'/')) {
4588 if (!strncasecmp(aux, name, strlen(aux))) {
4636 if (strchr(screenname,
'@') && message) {
4662 }
else if (res == -1)
4669 if (!iterator->thread)
4673 if (iterator->distribute_events) {
4702 if (device_state_sub) {
4709 ast_debug(3,
"JABBER: Releasing and disconnecting client: %s\n", iterator->name);
4712 pthread_join(iterator->thread, NULL);
static int aji_reconnect(struct aji_client *client)
static char * app_ajijoin
static char * aji_cli_purge_pubsub_nodes(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Method to purge PubSub nodes via CLI.
static void aji_request_pubsub_nodes(struct aji_client *client, const char *collection)
Request item list from pubsub.
enum sip_cc_notify_state state
static struct ast_custom_function jabberstatus_function
Main Channel structure associated with a channel.
#define AST_CLI_DEFINE(fn, txt,...)
static int aji_send_raw(struct aji_client *client, const char *xmlstr)
static iks * aji_pubsub_iq_create(struct aji_client *client, const char *type)
Create an IQ packet.
static int aji_start_sasl(struct aji_client *client, enum ikssasltype type, char *username, char *pass)
static int aji_client_connect(void *data, ikspak *pak)
static int aji_act_hook(void *data, int type, iks *node)
#define AST_LIST_LOCK(head)
Locks a list.
static int aji_initialize(struct aji_client *client)
Asterisk locking-related definitions:
void astman_append(struct mansession *s, const char *fmt,...)
#define AJI_MAX_RESJIDLEN
Asterisk main include file. File version handling, generic pbx functions.
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.
int ast_autoservice_start(struct ast_channel *chan)
Automatically service a channel for us...
char * strsep(char **str, const char *delims)
static int aji_send_exec(struct ast_channel *chan, const char *data)
struct aji_version * next
CallerID (and other GR30) management and generation Includes code and algorithms from the Zapata libr...
static char * aji_show_buddies(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
#define ast_alloca(size)
call __builtin_alloca to ensure we get gcc builtin semantics
int ast_aji_send(struct aji_client *client, iks *x)
Wraps raw sending.
int ast_cli_unregister_multiple(struct ast_cli_entry *e, int len)
Unregister multiple commands.
char * ast_eid_to_str(char *s, int maxlen, struct ast_eid *eid)
#define ast_set2_flag(p, value, flag)
#define ast_test_flag(p, flag)
static int aji_join_exec(struct ast_channel *chan, const char *data)
Application to join a chat room.
static void aji_init_event_distribution(struct aji_client *client)
Initialize collections for event distribution.
static int delete_old_messages_all(struct aji_client *client)
#define ast_set_flag(p, flag)
#define ASTOBJ_MARK(object)
Mark an ASTOBJ by adding the ASTOBJ_FLAG_MARKED flag to its objflags mask.
int ast_event_queue_and_cache(struct ast_event *event)
Queue and cache an event.
descriptor for a cli entry.
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
struct ast_variable * ast_variable_browse(const struct ast_config *config, const char *category)
Goes through variables.
int64_t ast_tvdiff_sec(struct timeval end, struct timeval start)
Computes the difference (in seconds) between two struct timeval instances.
static struct aji_capabilities * capabilities
static struct ast_flags globalflags
Global flags, initialized to default values.
void ast_verbose(const char *fmt,...)
int ast_aji_disconnect(struct aji_client *client)
disconnect from jabber server.
#define AST_DECLARE_APP_ARGS(name, arglist)
Declare a structure to hold an application's arguments.
const SSL_METHOD * ssl_method
#define ASTOBJ_UNMARK(object)
Unmark an ASTOBJ by subtracting the ASTOBJ_FLAG_MARKED flag from its objflags mask.
Structure for variables, used for configurations and for channel variables.
int ast_aji_join_chat(struct aji_client *client, char *room, char *nick)
join a chatroom.
static int manager_jabber_send(struct mansession *s, const struct message *m)
static void aji_handle_subscribe(struct aji_client *client, ikspak *pak)
static void aji_handle_message(struct aji_client *client, ikspak *pak)
int ast_enable_distributed_devstate(void)
Enable distributed device state processing.
static char * aji_do_reload(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Configuration File Parser.
static iks * aji_build_node_request(struct aji_client *client, const char *collection)
Build the a node request.
static int acf_jabberstatus_read(struct ast_channel *chan, const char *name, char *data, char *buf, size_t buflen)
static struct ast_flags pubsubflags
PubSub flags, initialized to default values.
#define ast_cond_init(cond, attr)
static int aji_send_raw_chat(struct aji_client *client, int groupchat, const char *nick, const char *address, const char *message)
sends messages.
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
#define ASTOBJ_WRLOCK(object)
Lock an ASTOBJ for writing.
Number of new messages Used by: AST_EVENT_MWI Payload type: UINT.
char serverhost[AJI_MAX_RESJIDLEN]
Number of Used by: AST_EVENT_MWI Payload type: UINT.
#define AST_LIST_EMPTY(head)
Checks whether the specified list contains any entries.
void astman_send_ack(struct mansession *s, const struct message *m, char *msg)
Send ack in manager transaction.
#define ast_mutex_lock(a)
#define AST_MODULE_INFO(keystr, flags_to_set, desc, fields...)
#define ast_copy_flags(dest, src, flagz)
int64_t ast_tvdiff_ms(struct timeval end, struct timeval start)
Computes the difference (in milliseconds) between two struct timeval instances.
static int aji_is_secure(struct aji_client *client)
Generic File Format Support. Should be included by clients of the file handling routines. File service providers should instead include mod_format.h.
static int aji_reload(int reload)
void ast_cli(int fd, const char *fmt,...)
static char * app_ajisendgroup
AJI - The Asterisk Jabber Interface.
int ast_unregister_application(const char *app)
Unregister an application.
#define AST_LIST_TRAVERSE_SAFE_END
Closes a safe loop traversal block.
An Entity ID is essentially a MAC address, brief and unique.
static char * aji_cli_create_collection(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Method to expose PubSub collection node creation via CLI.
#define ast_verb(level,...)
static iks * aji_create_pubsub_node(struct aji_client *client, const char *node_type, const char *name, const char *collection_name)
Create a pubsub node.
static void aji_pubsub_purge_nodes(struct aji_client *client, const char *collection_name)
void ast_config_destroy(struct ast_config *config)
Destroys a config.
static ast_cond_t message_received_condition
struct aji_capabilities * next
int ast_custom_function_unregister(struct ast_custom_function *acf)
Unregister a custom function.
Entity ID Used by All events Payload type: RAW This IE indicates which server the event originated fr...
static char * app_ajileave
int ast_eid_cmp(const struct ast_eid *eid1, const struct ast_eid *eid2)
Compare two EIDs.
int ast_aji_send_chat(struct aji_client *client, const char *address, const char *message)
sends messages.
static void aji_pubsub_subscribe(struct aji_client *client, const char *node)
Subscribe to a PubSub node.
int args
This gets set in ast_cli_register()
static void aji_set_presence(struct aji_client *client, char *to, char *from, int level, char *desc)
const char * astman_get_header(const struct message *m, char *var)
Get header from mananger transaction.
static int aji_status_exec(struct ast_channel *chan, const char *data)
int ast_aji_create_chat(struct aji_client *client, char *room, char *server, char *topic)
create a chatroom.
pthread_cond_t ast_cond_t
static iks * aji_build_node_config(iks *pubsub, const char *node_type, const char *collection_name)
#define AST_LIST_HEAD_DESTROY(head)
Destroys a list head structure.
#define ast_pthread_create_background(a, b, c, d)
#define CONFIG_STATUS_FILEMISSING
#define ASTOBJ_CONTAINER_INIT(container)
Initialize a container.
static int aji_create_client(char *label, struct ast_variable *var, int debug)
char resource[AJI_MAX_RESJIDLEN]
#define ast_asprintf(a, b, c...)
static int aji_client_info_handler(void *data, ikspak *pak)
static char * aji_cli_create_leafnode(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Method to expose PubSub leaf node creation via CLI.
static void aji_delete_pubsub_node(struct aji_client *client, const char *node_name)
Delete a PubSub node.
static void aji_log_hook(void *data, const char *xmpp, size_t size, int is_incoming)
static int aji_io_recv(struct aji_client *client, char *buffer, size_t buf_len, int timeout)
#define EVENT_FLAG_SYSTEM
static void aji_message_destroy(struct aji_message *obj)
static char * aji_cli_list_pubsub_nodes(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Method to expose PubSub node list via CLI.
#define ast_debug(level,...)
Log a DEBUG message.
int ast_event_queue(struct ast_event *event)
Queue an event.
Context IE Used by AST_EVENT_MWI Payload type: str.
static int delete_old_messages(struct aji_client *client, char *from)
unsigned int stream_flags
enum ast_device_state ast_devstate_val(const char *val)
Convert device state from text to integer value.
General Asterisk PBX channel definitions.
struct aji_buddy_container buddies
#define ast_config_load(filename, flags)
Load a config file.
#define ast_manager_register_xml(a, b, c)
Register a manager callback using XML documentation to describe the manager.
static force_inline int attribute_pure ast_strlen_zero(const char *s)
#define ast_poll(a, b, c)
struct sla_ringing_trunk * last
Data structure associated with a custom dialplan function.
Access Control of various sorts.
#define AST_MAX_EXTENSION
struct aji_version * versions
static int aji_register_query_handler(void *data, ikspak *pak)
#define AST_LIST_REMOVE_CURRENT(field)
Removes the current entry from a list during a traversal.
char * ast_category_browse(struct ast_config *config, const char *prev)
Goes through categories.
static int aji_ditems_handler(void *data, ikspak *pak)
static int unload_module(void)
static struct agi_command commands[]
AGI commands list.
int ast_str_to_eid(struct ast_eid *eid, const char *s)
Convert a string into an EID.
static iks * aji_build_publish_skeleton(struct aji_client *client, const char *node, const char *event_type, unsigned int cachable)
Build the skeleton of a publish.
#define ASTOBJ_INIT(object)
Initialize an object.
int ast_aji_invite_chat(struct aji_client *client, char *user, char *room, char *message)
invite to a chatroom.
static int aji_delete_node_list(void *data, ikspak *pak)
Delete pubsub item lists.
#define ast_cond_broadcast(cond)
#define AST_LIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.
struct aji_resource * next
Event non-cachability flag Used by: All events Payload type: UINT.
Core PBX routines and definitions.
int ast_autoservice_stop(struct ast_channel *chan)
Stop servicing a channel for us...
const void * ast_event_get_ie_raw(const struct ast_event *event, enum ast_event_ie_type ie_type)
Get the value of an information element that has a raw payload.
#define ASTOBJ_UNREF(object, destructor)
Decrement the reference count on an object.
void ast_sha1_hash(char *output, const char *input)
Produces SHA1 hash based on input string.
const char * ast_devstate_str(enum ast_device_state devstate) attribute_pure
Convert device state to text string that is easier to parse.
static struct ast_cli_entry aji_cli[]
static int aji_handle_pubsub_event(void *data, ikspak *pak)
Callback for handling PubSub events.
The AMI - Asterisk Manager Interface - is a TCP protocol created to manage Asterisk with third-party ...
void ast_event_dump_cache(const struct ast_event_sub *event_sub)
Dump the event cache for the subscriber.
#define ast_strdupa(s)
duplicate a string in memory from the stack
static char * aji_cli_delete_pubsub_node(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Method to expose PubSub node deletion via CLI.
#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".
char user[AJI_MAX_JIDLEN]
static int aji_get_roster(struct aji_client *client)
static void aji_handle_presence(struct aji_client *client, ikspak *pak)
#define ASTOBJ_CONTAINER_LINK(container, newobj)
Add an object to a container.
int ast_base64encode(char *dst, const unsigned char *src, int srclen, int max)
Encode data in base64.
int ast_aji_leave_chat(struct aji_client *client, char *room, char *nick)
leave a chatroom.
int ast_aji_send_groupchat(struct aji_client *client, const char *nick, const char *address, const char *message)
sends message to a groupchat Prior to sending messages to a groupchat, one must be connected to it...
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
struct timeval ast_tvadd(struct timeval a, struct timeval b)
Returns the sum of two timevals a + b.
const ast_string_field name
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...
static void aji_create_pubsub_collection(struct aji_client *client, const char *collection_name)
Create a PubSub collection node.
#define ast_cond_destroy(cond)
#define ASTOBJ_CONTAINER_TRAVERSE(container, continue, eval)
Iterate through the objects in a container.
static int aji_receive_node_list(void *data, ikspak *pak)
Receive pubsub item lists.
static void aji_publish_device_state(struct aji_client *client, const char *device, const char *device_state, unsigned int cachable)
Publish device state to a PubSub node.
#define AST_LIST_INSERT_HEAD(head, elm, field)
Inserts a list entry at the head of a list.
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) ...
static void parse(struct mgcp_request *req)
#define ASTOBJ_UNLOCK(object)
Unlock a locked object.
#define AST_LIST_HEAD_INIT(head)
Initializes a list head structure.
#define ASTOBJ_CONTAINER_FIND(container, namestr)
Find an object in a container.
static struct aji_version * aji_find_version(char *node, char *version, ikspak *pak)
static char * aji_show_clients(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static int load_module(void)
static char * app_ajistatus
if(yyss+yystacksize-1<=yyssp)
structure to hold users read from users.conf
Structure used to handle boolean flags.
static struct aji_client_container clients
#define ast_clear_flag(p, flag)
static struct ast_event_sub * device_state_sub
int pbx_builtin_setvar_helper(struct ast_channel *chan, const char *name, const char *value)
Add a variable to the channel variable stack, removing the most recently set value for the same name...
uint32_t ast_event_get_ie_uint(const struct ast_event *event, enum ast_event_ie_type ie_type)
Get the value of an information element that has an integer payload.
static iks * jabber_make_auth(iksid *id, const char *pass, const char *sid)
char pubsub_node[AJI_MAX_RESJIDLEN]
static int aji_dinfo_handler(void *data, ikspak *pak)
void ast_aji_client_destroy(struct aji_client *obj)
struct ast_eid ast_eid_default
Global EID.
static void aji_devstate_cb(const struct ast_event *ast_event, void *data)
Callback function for device state events.
static void aji_create_affiliations(struct aji_client *client, const char *node)
Add Owner affiliations for pubsub node.
static void aji_mwi_cb(const struct ast_event *ast_event, void *data)
Callback function for MWI events.
static int aji_load_config(int reload)
static int aji_filter_roster(void *data, ikspak *pak)
Standard Command Line Interface.
#define ASTOBJ_RDLOCK(object)
Lock an ASTOBJ for reading.
struct ast_event * ast_event_new(enum ast_event_type event_type,...)
Create a new event.
static int aji_register_approve_handler(void *data, ikspak *pak)
struct ast_event_sub * ast_event_subscribe(enum ast_event_type event_type, ast_event_cb_t cb, const char *description, void *userdata,...)
Subscribe to events.
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
static int aji_create_buddy(char *label, struct aji_client *client)
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one...
struct timeval ast_tv(ast_time_t sec, ast_suseconds_t usec)
Returns a timeval from sec, usec.
struct aji_message::@188 list
static int aji_recv(struct aji_client *client, int timeout)
int attribute_pure ast_false(const char *val)
Make sure something is false. Determine if a string containing a boolean value is "false"...
int ast_cli_register_multiple(struct ast_cli_entry *e, int len)
Register multiple commands.
static ast_mutex_t messagelock
Application convenience functions, designed to give consistent look and feel to Asterisk apps...
static int aji_tls_handshake(struct aji_client *client)
static int aji_set_group_presence(struct aji_client *client, char *room, int level, char *nick, char *desc)
static int aji_handle_pubsub_error(void *data, ikspak *pak)
static void * aji_recv_loop(void *data)
#define ASTOBJ_CONTAINER_MARKALL(container)
Mark all the objects in a container.
static struct aji_resource * aji_find_resource(struct aji_buddy *buddy, char *name)
static int gtalk_yuck(iks *node)
#define AST_APP_ARG(name)
Define an application argument.
#define AST_LIST_TRAVERSE_SAFE_BEGIN(head, var, field)
Loops safely over (traverses) the entries in a list.
struct ast_variable * next
#define ast_mutex_init(pmutex)
static void aji_publish_mwi(struct aji_client *client, const char *mailbox, const char *context, const char *oldmsgs, const char *newmsgs)
Publish MWI to a PubSub node.
#define AST_STANDARD_APP_ARGS(args, parse)
Performs the 'standard' argument separation process for an application.
#define CONFIG_STATUS_FILEINVALID
static char context[AST_MAX_CONTEXT]
#define ast_mutex_destroy(a)
Generic State IE Used by AST_EVENT_DEVICE_STATE_CHANGE Payload type: UINT The actual state values dep...
const char * ast_event_get_ie_str(const struct ast_event *event, enum ast_event_ie_type ie_type)
Get the value of an information element that has a string payload.
#define AST_NONSTANDARD_APP_ARGS(args, parse, sep)
Performs the 'nonstandard' argument separation process for an application.
static int aji_sendgroup_exec(struct ast_channel *chan, const char *data)
Application to send a message to a groupchat.
static int aji_leave_exec(struct ast_channel *chan, const char *data)
Application to leave a chat room.
#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.
#define ASTOBJ_REF(object)
Increment an object reference count.
void astman_send_error(struct mansession *s, const struct message *m, char *error)
Send error in manager transaction.
Asterisk module definitions.
Device Name Used by AST_EVENT_DEVICE_STATE_CHANGE Payload type: STR.
static struct ast_custom_function jabberreceive_function
struct aji_capabilities * parent
Persistant data storage (akin to *doze registry)
static void aji_create_pubsub_leaf(struct aji_client *client, const char *collection_name, const char *leaf_name)
Create a PubSub leaf node.
static int acf_jabberreceive_read(struct ast_channel *chan, const char *name, char *data, char *buf, size_t buflen)
struct ast_event_sub * ast_event_unsubscribe(struct ast_event_sub *event_sub)
Un-subscribe from events.
struct aji_client::messages messages
struct aji_resource * resources
#define ast_cond_timedwait(cond, mutex, time)
#define ast_custom_function_register(acf)
Register a custom function.
static int aji_send_header(struct aji_client *client, const char *to)
#define ast_register_application_xml(app, execute)
Register an application using XML documentation.
static void aji_handle_iq(struct aji_client *client, iks *node)
Structure for mutex and tracking information.
void ast_aji_increment_mid(char *mid)
increments the mid field for messages and other events.
static char mailbox[AST_MAX_EXTENSION]
int ast_manager_unregister(char *action)
Unregister a registered manager command.
#define ASTERISK_FILE_VERSION(file, version)
Register/unregister a source code file with the core.
static char * app_ajisend
#define ASTOBJ_CONTAINER_PRUNE_MARKED(container, destructor)
Prune marked objects from a container.
#define CONFIG_STATUS_FILEUNCHANGED
static int aji_start_tls(struct aji_client *client)
#define ast_mutex_unlock(a)
static char * aji_do_set_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
struct aji_client_container * ast_aji_get_clients(void)
static void aji_pruneregister(struct aji_client *client)