555#define CLIENT_BUCKETS 53 
  558#define BUDDY_BUCKETS 53 
  561#define RESOURCE_BUCKETS 53 
  564#define XMPP_TLS_NS "urn:ietf:params:xml:ns:xmpp-tls" 
  567#define STATUS_DISAPPEAR 6 
  691        iks_filter_delete(client->
filter);
 
  695        iks_stack_delete(client->
stack);
 
 
  710    const char *
id = obj;
 
 
  719    const char *
id = arg;
 
 
  770    if (!(client->
stack = iks_stack_new(8192, 8192))) {
 
 
  797    if (!cfg || !cfg->clients || !(clientcfg = 
xmpp_config_find(cfg->clients, category))) {
 
  801    ao2_ref(clientcfg->client, +1);
 
  802    return clientcfg->client;
 
 
  894        ast_log(
LOG_ERROR, 
"No oauth_clientid or oauth_secret specified, so client '%s' can't be used\n", clientcfg->
name);
 
  899    if (!cfg || !cfg->clients || !(oldclientcfg = 
xmpp_config_find(cfg->clients, clientcfg->
name))) {
 
  905    if (strcmp(clientcfg->
user, oldclientcfg->user) ||
 
  906        strcmp(clientcfg->
password, oldclientcfg->password) ||
 
  907        strcmp(clientcfg->
refresh_token, oldclientcfg->refresh_token) ||
 
  908        strcmp(clientcfg->
oauth_clientid, oldclientcfg->oauth_clientid) ||
 
  909        strcmp(clientcfg->
oauth_secret, oldclientcfg->oauth_secret) ||
 
  910        strcmp(clientcfg->
server, oldclientcfg->server) ||
 
  911        (clientcfg->
port != oldclientcfg->port) ||
 
  913        (clientcfg->
priority != oldclientcfg->priority)) {
 
 
  934    .category = 
"general",
 
 
  943    .category = 
"general",
 
  947    .item_offset = offsetof(
struct xmpp_config, clients),
 
 
  954    .alias = 
"jabber.conf",
 
 
 1004    return client->stream_flags & SECURE;
 
 
 1019    ao2_ref(clientcfg->client, +1);
 
 1020    return clientcfg->client;
 
 
 1045    iks *message_packet;
 
 1048        !(message_packet = iks_make_msg(
group ? IKS_TYPE_GROUPCHAT : IKS_TYPE_CHAT, 
address, 
message))) {
 
 1053        snprintf(from, 
sizeof(from), 
"%s@%s/%s", nick, client->
jid->full, nick);
 
 1055        snprintf(from, 
sizeof(from), 
"%s", client->
jid->full);
 
 1058    iks_insert_attrib(message_packet, 
"from", from);
 
 1062    iks_delete(message_packet);
 
 
 1075    iks *invite, *body = 
NULL, *
namespace = 
NULL;
 
 1077    if (!(invite = iks_new(
"message")) || !(body = iks_new(
"body")) || !(
namespace = iks_new(
"x"))) {
 
 1082    iks_insert_attrib(invite, 
"to", 
user);
 
 1084    iks_insert_attrib(invite, 
"id", client->
mid);
 
 1087    iks_insert_cdata(body, 
message, 0);
 
 1088    iks_insert_node(invite, body);
 
 1089    iks_insert_attrib(
namespace, 
"xmlns", 
"jabber:x:conference");
 
 1090    iks_insert_attrib(
namespace, 
"jid", room);
 
 1091    iks_insert_node(invite, 
namespace);
 
 1096    iks_delete(
namespace);
 
 
 1112        !(presence = iks_make_pres(level, 
NULL)) || !(x = iks_new(
"x"))) {
 
 1118        snprintf(from, 
sizeof(from), 
"%s@%s/%s", nick, client->
jid->full, nick);
 
 1119        snprintf(roomid, 
sizeof(roomid), 
"%s/%s", room, nick);
 
 1121        snprintf(from, 
sizeof(from), 
"%s", client->
jid->full);
 
 1122        snprintf(roomid, 
sizeof(roomid), 
"%s/%s", room, 
S_OR(nick, client->
jid->user));
 
 1125    iks_insert_attrib(presence, 
"to", roomid);
 
 1126    iks_insert_attrib(presence, 
"from", from);
 
 1127    iks_insert_attrib(x, 
"xmlns", 
"http://jabber.org/protocol/muc");
 
 1128    iks_insert_node(presence, x);
 
 1134    iks_delete(presence);
 
 
 1158    for (i = strlen(mid) - 1; i >= 0; i--) {
 
 1159        if (mid[i] != 
'z') {
 
 1160            mid[i] = mid[i] + 1;
 
 
 1186        iks_insert_attrib(
request, 
"to", clientcfg->pubsubnode);
 
 1189    iks_insert_attrib(
request, 
"from", client->
jid->full);
 
 1193    iks_insert_attrib(
request, 
"id", client->
mid);
 
 
 1207                           const char *event_type, 
unsigned int cachable)
 
 1216    pubsub = iks_insert(
request, 
"pubsub");
 
 1217    iks_insert_attrib(pubsub, 
"xmlns", 
"http://jabber.org/protocol/pubsub");
 
 1218    publish = iks_insert(pubsub, 
"publish");
 
 1221    iks_insert_attrib(
item, 
"id", 
node);
 
 1224        iks *
options, *x, *field_form_type, *field_persist;
 
 1226        options = iks_insert(pubsub, 
"publish-options");
 
 1228        iks_insert_attrib(x, 
"xmlns", 
"jabber:x:data");
 
 1229        iks_insert_attrib(x, 
"type", 
"submit");
 
 1230        field_form_type = iks_insert(x, 
"field");
 
 1231        iks_insert_attrib(field_form_type, 
"var", 
"FORM_TYPE");
 
 1232        iks_insert_attrib(field_form_type, 
"type", 
"hidden");
 
 1233        iks_insert_cdata(iks_insert(field_form_type, 
"value"), 
"http://jabber.org/protocol/pubsub#publish-options", 0);
 
 1234        field_persist = iks_insert(x, 
"field");
 
 1235        iks_insert_attrib(field_persist, 
"var", 
"pubsub#persist_items");
 
 1236        iks_insert_cdata(iks_insert(field_persist, 
"value"), 
"0", 1);
 
 
 1245    iks *configure, *x, *field_owner, *field_node_type, *field_node_config,
 
 1246        *field_deliver_payload, *field_persist_items, *field_access_model,
 
 1247        *field_pubsub_collection;
 
 1248    configure = iks_insert(pubsub, 
"configure");
 
 1249    x = iks_insert(configure, 
"x");
 
 1250    iks_insert_attrib(x, 
"xmlns", 
"jabber:x:data");
 
 1251    iks_insert_attrib(x, 
"type", 
"submit");
 
 1252    field_owner = iks_insert(x, 
"field");
 
 1253    iks_insert_attrib(field_owner, 
"var", 
"FORM_TYPE");
 
 1254    iks_insert_attrib(field_owner, 
"type", 
"hidden");
 
 1255    iks_insert_cdata(iks_insert(field_owner, 
"value"),
 
 1256             "http://jabber.org/protocol/pubsub#owner", 39);
 
 1258        field_node_type = iks_insert(x, 
"field");
 
 1259        iks_insert_attrib(field_node_type, 
"var", 
"pubsub#node_type");
 
 1260        iks_insert_cdata(iks_insert(field_node_type, 
"value"), 
node_type, strlen(
node_type));
 
 1262    field_node_config = iks_insert(x, 
"field");
 
 1263    iks_insert_attrib(field_node_config, 
"var", 
"FORM_TYPE");
 
 1264    iks_insert_attrib(field_node_config, 
"type", 
"hidden");
 
 1265    iks_insert_cdata(iks_insert(field_node_config, 
"value"),
 
 1266             "http://jabber.org/protocol/pubsub#node_config", 45);
 
 1267    field_deliver_payload = iks_insert(x, 
"field");
 
 1268    iks_insert_attrib(field_deliver_payload, 
"var", 
"pubsub#deliver_payloads");
 
 1269    iks_insert_cdata(iks_insert(field_deliver_payload, 
"value"), 
"1", 1);
 
 1270    field_persist_items = iks_insert(x, 
"field");
 
 1271    iks_insert_attrib(field_persist_items, 
"var", 
"pubsub#persist_items");
 
 1272    iks_insert_cdata(iks_insert(field_persist_items, 
"value"), 
"1", 1);
 
 1273    field_access_model = iks_insert(x, 
"field");
 
 1274    iks_insert_attrib(field_access_model, 
"var", 
"pubsub#access_model");
 
 1275    iks_insert_cdata(iks_insert(field_access_model, 
"value"), 
"whitelist", 9);
 
 1277        field_pubsub_collection = iks_insert(x, 
"field");
 
 1278        iks_insert_attrib(field_pubsub_collection, 
"var", 
"pubsub#collection");
 
 1279        iks_insert_cdata(iks_insert(field_pubsub_collection, 
"value"), collection_name,
 
 1280                 strlen(collection_name));
 
 
 1293    iks *pubsub, *affiliations, *affiliate;
 
 1297    if (!modify_affiliates) {
 
 1298        ast_log(
LOG_ERROR, 
"Could not create IQ for creating affiliations on client '%s'\n", client->
name);
 
 1302    pubsub = iks_insert(modify_affiliates, 
"pubsub");
 
 1303    iks_insert_attrib(pubsub, 
"xmlns", 
"http://jabber.org/protocol/pubsub#owner");
 
 1304    affiliations = iks_insert(pubsub, 
"affiliations");
 
 1305    iks_insert_attrib(affiliations, 
"node", 
node);
 
 1309        affiliate = iks_insert(affiliations, 
"affiliation");
 
 1310        iks_insert_attrib(affiliate, 
"jid", buddy->
id);
 
 1311        iks_insert_attrib(affiliate, 
"affiliation", 
"owner");
 
 1317    iks_delete(modify_affiliates);
 
 
 1328                    char *
name, 
const char *collection_name)
 
 1330    iks *
node, *pubsub, *create;
 
 1336    pubsub = iks_insert(
node, 
"pubsub");
 
 1337    iks_insert_attrib(pubsub, 
"xmlns", 
"http://jabber.org/protocol/pubsub");
 
 1338    create = iks_insert(pubsub, 
"create");
 
 1339    iks_insert_attrib(create, 
"node", 
name);
 
 
 1353    iks *
request, *pubsub, *
delete;
 
 1359    pubsub = iks_insert(
request, 
"pubsub");
 
 1360    iks_insert_attrib(pubsub, 
"xmlns", 
"http://jabber.org/protocol/pubsub#owner");
 
 1361    delete = iks_insert(pubsub, 
"delete");
 
 1362    iks_insert_attrib(
delete, 
"node", node_name);
 
 
 1386                    const char *leaf_name)
 
 
 1399    const char *oldmsgs, 
const char *newmsgs)
 
 1411    mailbox_node = iks_insert(
request, 
"mailbox");
 
 1412    iks_insert_attrib(mailbox_node, 
"xmlns", 
"http://asterisk.org");
 
 1413    iks_insert_attrib(mailbox_node, 
"eid", eid_str);
 
 1414    iks_insert_cdata(iks_insert(mailbox_node, 
"NEWMSGS"), newmsgs, strlen(newmsgs));
 
 1415    iks_insert_cdata(iks_insert(mailbox_node, 
"OLDMSGS"), oldmsgs, strlen(oldmsgs));
 
 
 1430                         const char *device_state, 
unsigned int cachable)
 
 1434    char eid_str[20], cachable_str[2];
 
 1450    iks_insert_attrib(
state, 
"xmlns", 
"http://asterisk.org");
 
 1451    iks_insert_attrib(
state, 
"eid", eid_str);
 
 1452    snprintf(cachable_str, 
sizeof(cachable_str), 
"%u", cachable);
 
 1453    iks_insert_attrib(
state, 
"cachable", cachable_str);
 
 1454    iks_insert_cdata(
state, device_state, strlen(device_state));
 
 
 1467    char oldmsgs[10], newmsgs[10];
 
 1481    snprintf(oldmsgs, 
sizeof(oldmsgs), 
"%d", mwi_state->
old_msgs);
 
 1482    snprintf(newmsgs, 
sizeof(newmsgs), 
"%d", mwi_state->
new_msgs);
 
 
 1520        ast_log(
LOG_ERROR, 
"Could not create IQ when creating pubsub unsubscription on client '%s'\n", client->
name);
 
 1524    pubsub = iks_insert(
request, 
"pubsub");
 
 1525    iks_insert_attrib(pubsub, 
"xmlns", 
"http://jabber.org/protocol/pubsub");
 
 
 1545    if (!cfg || !cfg->global || !
request) {
 
 1546        ast_log(
LOG_ERROR, 
"Could not create IQ when creating pubsub subscription on client '%s'\n", client->
name);
 
 1550    pubsub = iks_insert(
request, 
"pubsub");
 
 1551    iks_insert_attrib(pubsub, 
"xmlns", 
"http://jabber.org/protocol/pubsub");
 
 1552    subscribe = iks_insert(pubsub, 
"subscribe");
 
 1553    iks_insert_attrib(
subscribe, 
"jid", client->
jid->partial);
 
 1556        iks *
options, *x, *sub_options, *sub_type, *sub_depth, *sub_expire;
 
 1557        options = iks_insert(pubsub, 
"options");
 
 1559        iks_insert_attrib(x, 
"xmlns", 
"jabber:x:data");
 
 1560        iks_insert_attrib(x, 
"type", 
"submit");
 
 1561        sub_options = iks_insert(x, 
"field");
 
 1562        iks_insert_attrib(sub_options, 
"var", 
"FORM_TYPE");
 
 1563        iks_insert_attrib(sub_options, 
"type", 
"hidden");
 
 1564        iks_insert_cdata(iks_insert(sub_options, 
"value"),
 
 1565                 "http://jabber.org/protocol/pubsub#subscribe_options", 51);
 
 1566        sub_type = iks_insert(x, 
"field");
 
 1567        iks_insert_attrib(sub_type, 
"var", 
"pubsub#subscription_type");
 
 1568        iks_insert_cdata(iks_insert(sub_type, 
"value"), 
"items", 5);
 
 1569        sub_depth = iks_insert(x, 
"field");
 
 1570        iks_insert_attrib(sub_depth, 
"var", 
"pubsub#subscription_depth");
 
 1571        iks_insert_cdata(iks_insert(sub_depth, 
"value"), 
"all", 3);
 
 1572        sub_expire = iks_insert(x, 
"field");
 
 1573        iks_insert_attrib(sub_expire, 
"var", 
"pubsub#expire");
 
 1574        iks_insert_cdata(iks_insert(sub_expire, 
"value"), 
"presence", 8);
 
 
 1588    char *item_id, *device_state, *mailbox, *cachable_str;
 
 1589    int oldmsgs, newmsgs;
 
 1590    iks *
item, *item_content;
 
 1593    item = iks_find(iks_find(iks_find(pak->x, 
"event"), 
"items"), 
"item");
 
 1596        return IKS_FILTER_EAT;
 
 1598    item_id = iks_find_attrib(
item, 
"id");
 
 1599    item_content = iks_child(
item);
 
 1600    ast_str_to_eid(&pubsub_eid, iks_find_attrib(item_content, 
"eid"));
 
 1602        ast_debug(1, 
"Returning here, eid of incoming event matches ours!\n");
 
 1603        return IKS_FILTER_EAT;
 
 1605    if (!strcasecmp(iks_name(item_content), 
"state")) {
 
 1606        if ((cachable_str = iks_find_attrib(item_content, 
"cachable"))) {
 
 1607            sscanf(cachable_str, 
"%30u", &cachable);
 
 1609        device_state = iks_find_cdata(
item, 
"state");
 
 1614        return IKS_FILTER_EAT;
 
 1615    } 
else if (!strcasecmp(iks_name(item_content), 
"mailbox")) {
 
 1616        mailbox = 
strsep(&item_id, 
"@");
 
 1617        sscanf(iks_find_cdata(item_content, 
"OLDMSGS"), 
"%10d", &oldmsgs);
 
 1618        sscanf(iks_find_cdata(item_content, 
"NEWMSGS"), 
"%10d", &newmsgs);
 
 1622        return IKS_FILTER_EAT;
 
 1624        ast_debug(1, 
"Don't know how to handle PubSub event of type %s\n",
 
 1625              iks_name(item_content));
 
 1626        return IKS_FILTER_EAT;
 
 1629    return IKS_FILTER_EAT;
 
 
 1635    char *node_name, *
error;
 
 1637    iks *orig_request, *orig_pubsub = iks_find(pak->x, 
"pubsub");
 
 1640    if (!cfg || !cfg->global) {
 
 1642        return IKS_FILTER_EAT;
 
 1646        ast_debug(1, 
"Error isn't a PubSub error, why are we here?\n");
 
 1647        return IKS_FILTER_EAT;
 
 1650    orig_request = iks_child(orig_pubsub);
 
 1651    error = iks_find_attrib(iks_find(pak->x, 
"error"), 
"code");
 
 1652    node_name = iks_find_attrib(orig_request, 
"node");
 
 1654    if (!sscanf(
error, 
"%30d", &error_num)) {
 
 1655        return IKS_FILTER_EAT;
 
 1658    if (error_num > 399 && error_num < 500 && error_num != 404) {
 
 1660            "Error performing operation on PubSub node %s, %s.\n", node_name, 
error);
 
 1661        return IKS_FILTER_EAT;
 
 1662    } 
else if (error_num > 499 && error_num < 600) {
 
 1664        return IKS_FILTER_EAT;
 
 1667    if (!strcasecmp(iks_name(orig_request), 
"publish")) {
 
 1671            if (iks_find(iks_find(orig_request, 
"item"), 
"state")) {
 
 1673            } 
else if (iks_find(iks_find(orig_request, 
"item"), 
"mailbox")) {
 
 1681            iks_insert_node(
request, orig_pubsub);
 
 1688        return IKS_FILTER_EAT;
 
 1689    } 
else if (!strcasecmp(iks_name(orig_request), 
"subscribe")) {
 
 1697    return IKS_FILTER_EAT;
 
 
 1744                IKS_PAK_MESSAGE, IKS_RULE_FROM, clientcfg->pubsubnode, IKS_RULE_DONE);
 
 1746                IKS_PAK_IQ, IKS_RULE_SUBTYPE, IKS_TYPE_ERROR, IKS_RULE_DONE);
 
 
 1756#define BUDDY_OFFLINE 6 
 1757#define BUDDY_NOT_IN_ROSTER 7 
 1814    if (
args.argc != 2) {
 
 1815        ast_log(
LOG_ERROR, 
"JABBER_STATUS requires 2 arguments: sender and jid.\n");
 
 1820    if (jid.argc < 1 || jid.argc > 2) {
 
 
 1836    .
name = 
"JABBER_STATUS",
 
 
 1865    if (
args.argc < 2 || 
args.argc > 3) {
 
 1870    if (strchr(
args.jid, 
'/')) {
 
 1882            snprintf(nick, 
sizeof(nick), 
"asterisk");
 
 1884            snprintf(nick, 
sizeof(nick), 
"%s", clientcfg->client->jid->user);
 
 1887        snprintf(nick, 
sizeof(nick), 
"%s", 
args.nick);
 
 
 1924    if (
args.argc < 2 || 
args.argc > 3) {
 
 1929    if (strchr(
args.jid, 
'/')) {
 
 1946            snprintf(nick, 
sizeof(nick), 
"asterisk");
 
 1948            snprintf(nick, 
sizeof(nick), 
"%s", clientcfg->client->jid->user);
 
 1951        snprintf(nick, 
sizeof(nick), 
"%s", 
args.nick);
 
 
 2039            snprintf(nick, 
sizeof(nick), 
"asterisk");
 
 2041            snprintf(nick, 
sizeof(nick), 
"%s", clientcfg->client->jid->user);
 
 2044        snprintf(nick, 
sizeof(nick), 
"%s", 
args.nick);
 
 
 2067    int timeout, jidlen, resourcelen, found = 0;
 
 2068    struct timeval start;
 
 2089    if (
args.argc < 2 || 
args.argc > 3) {
 
 2104        sscanf(
args.timeout, 
"%d", &timeout);
 
 2111    jidlen = strlen(jid.screenname);
 
 2112    resourcelen = 
ast_strlen_zero(jid.resource) ? 0 : strlen(jid.resource);
 
 2119    ast_debug(3, 
"Waiting for an XMPP message from %s\n", 
args.jid);
 
 2130    while (diff < timeout) {
 
 2131        struct timespec ts = { 0, };
 
 2132        struct timeval wait;
 
 2136        ts.tv_sec = wait.tv_sec;
 
 2137        ts.tv_nsec = wait.tv_usec * 1000;
 
 2145        if (res == ETIMEDOUT) {
 
 2146            ast_debug(3, 
"No message received from %s in %d seconds\n", 
args.jid, timeout);
 
 2152            if (jid.argc == 1) {
 
 2154                if (strncasecmp(jid.screenname, 
message->from, jidlen)) {
 
 2159                char *resource = strchr(
message->from, 
'/');
 
 2160                if (!resource || strlen(resource) == 0) {
 
 2162                    if (strncasecmp(jid.screenname, 
message->from, jidlen)) {
 
 2167                    if (strncasecmp(jid.screenname, 
message->from, jidlen) || strncmp(jid.resource, resource, resourcelen)) {
 
 
 2209    .
name = 
"JABBER_RECEIVE",
 
 
 2225    int deleted = 0, isold = 0;
 
 
 2259    char *sender, *dest;
 
 2272    if (!cfg || !cfg->clients || !(clientcfg = 
xmpp_config_find(cfg->clients, sender))) {
 
 2277    ast_debug(1, 
"Sending message to '%s' from '%s'\n", dest, clientcfg->name);
 
 2283    return res == IKS_OK ? 0 : -1;
 
 
 2323                               "Goodbye. Your status is no longer required.\n"))) {
 
 2327    if (!(iq = iks_new(
"iq")) || !(query = iks_new(
"query")) || !(
item = iks_new(
"item"))) {
 
 2328        ast_log(
LOG_WARNING, 
"Could not allocate memory for roster removal of '%s' from client '%s'\n",
 
 2333    iks_insert_attrib(iq, 
"from", client->
jid->full);
 
 2334    iks_insert_attrib(iq, 
"type", 
"set");
 
 2335    iks_insert_attrib(query, 
"xmlns", 
"jabber:iq:roster");
 
 2336    iks_insert_node(iq, query);
 
 2337    iks_insert_attrib(
item, 
"jid", 
user);
 
 2338    iks_insert_attrib(
item, 
"subscription", 
"remove");
 
 2339    iks_insert_node(query, 
item);
 
 2342        ast_log(
LOG_WARNING, 
"Could not send roster removal request of '%s' from client '%s'\n",
 
 
 2365                               "Greetings! I am the Asterisk Open Source PBX and I want to subscribe to your presence\n"))) {
 
 2367            buddy->
id, client->
name);
 
 
 2384        return IKS_FILTER_EAT;
 
 2390        if (iks_strcmp(iks_name(
item), 
"item")) {
 
 2400                        iks_find_attrib(
item, 
"jid"), client->
name);
 
 2406                ast_log(
LOG_ERROR, 
"Could not allocate buddy '%s' on client '%s'\n", iks_find_attrib(
item, 
"jid"),
 
 2413        if (!iks_strcmp(iks_find_attrib(
item, 
"subscription"), 
"none") ||
 
 2414            !iks_strcmp(iks_find_attrib(
item, 
"subscription"), 
"from")) {
 
 2430    return IKS_FILTER_EAT;
 
 
 2442        !(presence = iks_make_pres(level, 
desc)) || !(cnode = iks_new(
"c")) || !(
priority = iks_new(
"priority"))) {
 
 2443        ast_log(
LOG_ERROR, 
"Unable to allocate stanzas for setting presence status for client '%s'\n", client->
name);
 
 2448        iks_insert_attrib(presence, 
"to", to);
 
 2452        iks_insert_attrib(presence, 
"from", from);
 
 2455    snprintf(priorityS, 
sizeof(priorityS), 
"%d", clientcfg->priority);
 
 2456    iks_insert_cdata(
priority, priorityS, strlen(priorityS));
 
 2457    iks_insert_node(presence, 
priority);
 
 2458    iks_insert_attrib(cnode, 
"node", 
"http://www.asterisk.org/xmpp/client/caps");
 
 2459    iks_insert_attrib(cnode, 
"ver", 
"asterisk-xmpp");
 
 2460    iks_insert_attrib(cnode, 
"ext", 
"voice-v1 video-v1 camera-v1");
 
 2461    iks_insert_attrib(cnode, 
"xmlns", 
"http://jabber.org/protocol/caps");
 
 2462    iks_insert_node(presence, cnode);
 
 2467    iks_delete(presence);
 
 
 2477    if (!(iq = iks_new(
"iq")) || !(query = iks_new(
"query")) || !(ident = iks_new(
"identity")) || !(disco = iks_new(
"feature")) ||
 
 2478        !(google = iks_new(
"feature")) || !(jingle = iks_new(
"feature")) || !(ice = iks_new(
"feature")) || !(rtp = iks_new(
"feature")) ||
 
 2479        !(audio = iks_new(
"feature")) || !(video = iks_new(
"feature"))) {
 
 2480        ast_log(
LOG_ERROR, 
"Could not allocate memory for responding to service discovery request from '%s' on client '%s'\n",
 
 2481            pak->from->full, client->
name);
 
 2485    iks_insert_attrib(iq, 
"from", client->
jid->full);
 
 2488        iks_insert_attrib(iq, 
"to", pak->from->full);
 
 2491    iks_insert_attrib(iq, 
"type", 
"result");
 
 2492    iks_insert_attrib(iq, 
"id", pak->id);
 
 2493    iks_insert_attrib(query, 
"xmlns", 
"http://jabber.org/protocol/disco#info");
 
 2494    iks_insert_attrib(ident, 
"category", 
"client");
 
 2495    iks_insert_attrib(ident, 
"type", 
"pc");
 
 2496    iks_insert_attrib(ident, 
"name", 
"asterisk");
 
 2497    iks_insert_attrib(disco, 
"var", 
"http://jabber.org/protocol/disco#info");
 
 2499    iks_insert_attrib(google, 
"var", 
"http://www.google.com/xmpp/protocol/voice/v1");
 
 2500    iks_insert_attrib(jingle, 
"var", 
"urn:xmpp:jingle:1");
 
 2501    iks_insert_attrib(ice, 
"var", 
"urn:xmpp:jingle:transports:ice-udp:1");
 
 2502    iks_insert_attrib(rtp, 
"var", 
"urn:xmpp:jingle:apps:rtp:1");
 
 2503    iks_insert_attrib(audio, 
"var", 
"urn:xmpp:jingle:apps:rtp:audio");
 
 2504    iks_insert_attrib(video, 
"var", 
"urn:xmpp:jingle:apps:rtp:video");
 
 2505    iks_insert_node(iq, query);
 
 2506    iks_insert_node(query, ident);
 
 2507    iks_insert_node(query, google);
 
 2508    iks_insert_node(query, disco);
 
 2509    iks_insert_node(query, jingle);
 
 2510    iks_insert_node(query, ice);
 
 2511    iks_insert_node(query, rtp);
 
 2512    iks_insert_node(query, audio);
 
 2513    iks_insert_node(query, video);
 
 2528    return IKS_FILTER_EAT;
 
 
 2539        return IKS_FILTER_EAT;
 
 2544        return IKS_FILTER_EAT;
 
 2549    if (iks_find_with_attrib(pak->query, 
"feature", 
"var", 
"urn:xmpp:jingle:1")) {
 
 2558    return IKS_FILTER_EAT;
 
 
 2573    client->
jid = (iks_find_cdata(pak->query, 
"jid")) ? iks_id_new(client->
stack, iks_find_cdata(pak->query, 
"jid")) : client->
jid;
 
 2579    if (!(roster = iks_make_iq(IKS_TYPE_GET, IKS_NS_ROSTER))) {
 
 2580        ast_log(
LOG_ERROR, 
"Unable to allocate memory for roster request for client '%s'\n", client->
name);
 
 2587    iks_insert_attrib(roster, 
"id", 
"roster");
 
 2591    iks_filter_add_rule(client->
filter, 
xmpp_roster_hook, client, IKS_RULE_TYPE, IKS_PAK_IQ, IKS_RULE_SUBTYPE, IKS_TYPE_RESULT, IKS_RULE_ID, 
"roster", IKS_RULE_DONE);
 
 2596    return IKS_FILTER_EAT;
 
 
 2600static void xmpp_log_hook(
void *data, 
const char *xmpp, 
size_t size, 
int incoming)
 
 2611        ast_verbose(
"\n<--- XMPP sent to '%s' --->\n%s\n<------------->\n", client->
name, xmpp);
 
 2613        ast_verbose(
"\n<--- XMPP received from '%s' --->\n%s\n<------------->\n", client->
name, xmpp);
 
 
 2624        return IKS_NET_NOCONN;
 
 2631        ret = SSL_write(client->ssl_session, 
message, 
len);
 
 2643    if (ret != IKS_OK) {
 
 
 2654    char msg[91 + strlen(
namespace) + 6 + strlen(to) + 16 + 1];
 
 2656    snprintf(msg, 
sizeof(msg), 
"<?xml version='1.0'?>" 
 2657         "<stream:stream xmlns:stream='http://etherx.jabber.org/streams' xmlns='" 
 2658         "%s' to='%s' version='1.0'>", 
namespace, to);
 
 
 2678    ast_log(
LOG_ERROR, 
"TLS connection for client '%s' cannot be established. OpenSSL is not available.\n", client->
name);
 
 2681    if (iks_send_raw(client->
parser, 
"<starttls xmlns='urn:ietf:params:xml:ns:xmpp-tls'/>") == IKS_NET_TLSFAIL) {
 
 2686    client->stream_flags |= TRY_SECURE;
 
 
 2695static char *openssl_error_string(
void)
 
 2699    BIO *bio = BIO_new(BIO_s_mem());
 
 2701    ERR_print_errors(bio);
 
 2702    len = BIO_get_mem_data(bio, &
buf);
 
 2721    if (!strcmp(iks_name(
node), 
"success")) {
 
 2725    } 
else if (!strcmp(iks_name(
node), 
"failure")) {
 
 2728    } 
else if (strcmp(iks_name(
node), 
"proceed")) {
 
 2734    ast_log(
LOG_ERROR, 
"Somehow we managed to try to start TLS negotiation on client '%s' without OpenSSL support, disconnecting\n", client->
name);
 
 2737    client->ssl_method = SSLv23_method();
 
 2738    if (!(client->ssl_context = SSL_CTX_new((SSL_METHOD *) client->ssl_method))) {
 
 2742    ssl_opts = SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3;
 
 2743    SSL_CTX_set_options(client->ssl_context, ssl_opts);
 
 2745    if (!(client->ssl_session = SSL_new(client->ssl_context))) {
 
 2749    sock = iks_fd(client->
parser);
 
 2750    if (!SSL_set_fd(client->ssl_session, sock)) {
 
 2754    if (SSL_connect(client->ssl_session) <= 0) {
 
 2758    client->stream_flags &= (~TRY_SECURE);
 
 2759    client->stream_flags |= SECURE;
 
 2762        ast_log(
LOG_ERROR, 
"TLS connection for client '%s' could not be established, failed to send stream header after negotiation\n",
 
 2767    ast_debug(1, 
"TLS connection for client '%s' started with server\n", client->
name);
 
 2774    err = openssl_error_string();
 
 2775    ast_log(
LOG_ERROR, 
"TLS connection for client '%s' cannot be established. " 
 2776        "OpenSSL initialization failed: %s\n", client->
name, err);
 
 
 2786    char buf[41], sidpass[100];
 
 2788    if (!(iq = iks_new(
"iq")) || !(query = iks_insert(iq, 
"query"))) {
 
 2789        ast_log(
LOG_ERROR, 
"Stanzas could not be allocated for authentication on client '%s'\n", client->
name);
 
 2794    iks_insert_attrib(iq, 
"type", 
"set");
 
 2795    iks_insert_cdata(iks_insert(query, 
"username"), client->
jid->user, 0);
 
 2796    iks_insert_cdata(iks_insert(query, 
"resource"), client->
jid->resource, 0);
 
 2798    iks_insert_attrib(query, 
"xmlns", 
"jabber:iq:auth");
 
 2799    snprintf(sidpass, 
sizeof(sidpass), 
"%s%s", iks_find_attrib(
node, 
"id"), cfg->
password);
 
 2801    iks_insert_cdata(iks_insert(query, 
"digest"), 
buf, 0);
 
 2804    iks_filter_add_rule(client->
filter, 
xmpp_connect_hook, client, IKS_RULE_TYPE, IKS_PAK_IQ, IKS_RULE_SUBTYPE, IKS_TYPE_RESULT, IKS_RULE_ID, client->
mid, IKS_RULE_DONE);
 
 2805    iks_insert_attrib(iq, 
"id", client->
mid);
 
 2809    iks_insert_attrib(iq, 
"to", client->
jid->server);
 
 
 2823    int features, 
len = strlen(client->
jid->user) + strlen(cfg->
password) + 3;
 
 2828    if (strcmp(iks_name(
node), 
"stream:features")) {
 
 2833    features = iks_stream_features(
node);
 
 2835    if ((features & IKS_STREAM_SASL_MD5) && !
xmpp_is_secure(client)) {
 
 2836        if (iks_start_sasl(client->
parser, IKS_SASL_DIGEST_MD5, (
char*)client->
jid->user, (
char*)cfg->
password) != IKS_OK) {
 
 2837            ast_log(
LOG_ERROR, 
"Tried to authenticate client '%s' using SASL DIGEST-MD5 but could not\n", client->
name);
 
 2846    if (!(features & IKS_STREAM_SASL_PLAIN)) {
 
 2847        ast_log(
LOG_ERROR, 
"Tried to authenticate client '%s' using SASL PLAIN but server does not support it\n", client->
name);
 
 2851    if (!(auth = iks_new(
"auth"))) {
 
 2852        ast_log(
LOG_ERROR, 
"Could not allocate memory for SASL PLAIN authentication for client '%s'\n", client->
name);
 
 2856    iks_insert_attrib(auth, 
"xmlns", IKS_NS_XMPP_SASL);
 
 2858        iks_insert_attrib(auth, 
"mechanism", 
"X-OAUTH2");
 
 2859        iks_insert_attrib(auth, 
"auth:service", 
"oauth2");
 
 2860        iks_insert_attrib(auth, 
"xmlns:auth", 
"http://www.google.com/talk/protocol/auth");
 
 2862        iks_insert_attrib(auth, 
"mechanism", 
"PLAIN");
 
 2865    if (strchr(client->
jid->user, 
'/')) {
 
 2868        snprintf(combined, 
sizeof(combined), 
"%c%s%c%s", 0, 
strsep(&
user, 
"/"), 0, cfg->
password);
 
 2870        snprintf(combined, 
sizeof(combined), 
"%c%s%c%s", 0, client->
jid->user, 0, cfg->
password);
 
 2874    iks_insert_cdata(auth, 
base64, 0);
 
 
 2896    if (!strcmp(iks_name(
node), 
"success")) {
 
 2901    } 
else if (!strcmp(iks_name(
node), 
"failure")) {
 
 2904    } 
else if (strcmp(iks_name(
node), 
"stream:features")) {
 
 2909    features = iks_stream_features(
node);
 
 2911    if (features & IKS_STREAM_BIND) {
 
 2914        if (!(auth = iks_make_resource_bind(client->
jid))) {
 
 2915            ast_log(
LOG_ERROR, 
"Failed to allocate memory for stream bind on client '%s'\n", client->
name);
 
 2920        iks_insert_attrib(auth, 
"id", client->
mid);
 
 2927        iks_filter_add_rule(client->
filter, 
xmpp_connect_hook, client, IKS_RULE_TYPE, IKS_PAK_IQ, IKS_RULE_SUBTYPE, IKS_TYPE_RESULT, IKS_RULE_DONE);
 
 2930    if (features & IKS_STREAM_SESSION) {
 
 2933        if (!(auth = iks_make_session())) {
 
 2934            ast_log(
LOG_ERROR, 
"Failed to allocate memory for stream session on client '%s'\n", client->
name);
 
 2938        iks_insert_attrib(auth, 
"id", 
"auth");
 
 2946        iks_filter_add_rule(client->
filter, 
xmpp_connect_hook, client, IKS_RULE_TYPE, IKS_PAK_IQ, IKS_RULE_SUBTYPE, IKS_TYPE_RESULT, IKS_RULE_ID, 
"auth", IKS_RULE_DONE);
 
 
 2955    char secret[160], shasum[320], 
message[344];
 
 2956    ikspak *pak = iks_packet(
node);
 
 2958    snprintf(secret, 
sizeof(secret), 
"%s%s", pak->id, cfg->
password);
 
 2960    snprintf(
message, 
sizeof(
message), 
"<handshake>%s</handshake>", shasum);
 
 
 2983        !(iq = iks_new(
"iq")) || !(query = iks_new(
"query")) || !(identity = iks_new(
"identity")) || !(disco = iks_new(
"feature")) ||
 
 2984        !(reg = iks_new(
"feature")) || !(
commands = iks_new(
"feature")) || !(gateway = iks_new(
"feature")) || !(
version = iks_new(
"feature")) ||
 
 2985        !(vcard = iks_new(
"feature")) || !(search = iks_new(
"search")) || !(
item = iks_new(
"item"))) {
 
 2986        ast_log(
LOG_ERROR, 
"Failed to allocate stanzas for service discovery get response to '%s' on component '%s'\n",
 
 2987            pak->from->partial, client->
name);
 
 2991    iks_insert_attrib(iq, 
"from", clientcfg->user);
 
 2992    iks_insert_attrib(iq, 
"to", pak->from->full);
 
 2993    iks_insert_attrib(iq, 
"id", pak->id);
 
 2994    iks_insert_attrib(iq, 
"type", 
"result");
 
 2996    if (!(
node = iks_find_attrib(pak->query, 
"node"))) {
 
 2997        iks_insert_attrib(query, 
"xmlns", 
"http://jabber.org/protocol/disco#info");
 
 2998        iks_insert_attrib(identity, 
"category", 
"gateway");
 
 2999        iks_insert_attrib(identity, 
"type", 
"pstn");
 
 3000        iks_insert_attrib(identity, 
"name", 
"Asterisk The Open Source PBX");
 
 3001        iks_insert_attrib(disco, 
"var", 
"http://jabber.org/protocol/disco");
 
 3002        iks_insert_attrib(reg, 
"var", 
"jabber:iq:register");
 
 3003        iks_insert_attrib(
commands, 
"var", 
"http://jabber.org/protocol/commands");
 
 3004        iks_insert_attrib(gateway, 
"var", 
"jabber:iq:gateway");
 
 3005        iks_insert_attrib(
version, 
"var", 
"jabber:iq:version");
 
 3006        iks_insert_attrib(vcard, 
"var", 
"vcard-temp");
 
 3007        iks_insert_attrib(search, 
"var", 
"jabber:iq:search");
 
 3009        iks_insert_node(iq, query);
 
 3010        iks_insert_node(query, identity);
 
 3011        iks_insert_node(query, disco);
 
 3012        iks_insert_node(query, reg);
 
 3014        iks_insert_node(query, gateway);
 
 3015        iks_insert_node(query, 
version);
 
 3016        iks_insert_node(query, vcard);
 
 3017        iks_insert_node(query, search);
 
 3018    } 
else if (!strcasecmp(
node, 
"http://jabber.org/protocol/commands")) {
 
 3019        iks_insert_attrib(query, 
"xmlns", 
"http://jabber.org/protocol/disco#items");
 
 3020        iks_insert_attrib(query, 
"node", 
"http://jabber.org/protocol/commands");
 
 3021        iks_insert_attrib(
item, 
"node", 
"confirmaccount");
 
 3022        iks_insert_attrib(
item, 
"name", 
"Confirm account");
 
 3023        iks_insert_attrib(
item, 
"jid", clientcfg->user);
 
 3025        iks_insert_node(iq, query);
 
 3026        iks_insert_node(query, 
item);
 
 3027    } 
else if (!strcasecmp(
node, 
"confirmaccount")) {
 
 3028        iks_insert_attrib(query, 
"xmlns", 
"http://jabber.org/protocol/disco#info");
 
 3029        iks_insert_attrib(
commands, 
"var", 
"http://jabber.org/protocol/commands");
 
 3031        iks_insert_node(iq, query);
 
 3034        ast_debug(3, 
"Unsupported service discovery info request received with node '%s' on component '%s'\n",
 
 3040        ast_log(
LOG_WARNING, 
"Could not send response to service discovery request on component '%s'\n",
 
 3048    iks_delete(gateway);
 
 3052    iks_delete(identity);
 
 3056    return IKS_FILTER_EAT;
 
 
 3070        !(iq = iks_new(
"iq")) || !(query = iks_new(
"query")) || !(
error = iks_new(
"error")) || !(notacceptable = iks_new(
"not-acceptable")) ||
 
 3071        !(instructions = iks_new(
"instructions"))) {
 
 3072        ast_log(
LOG_ERROR, 
"Failed to allocate stanzas for register get response to '%s' on component '%s'\n",
 
 3073            pak->from->partial, client->
name);
 
 3077    iks_insert_attrib(iq, 
"from", clientcfg->user);
 
 3078    iks_insert_attrib(iq, 
"to", pak->from->full);
 
 3079    iks_insert_attrib(iq, 
"id", pak->id);
 
 3080    iks_insert_attrib(iq, 
"type", 
"result");
 
 3081    iks_insert_attrib(query, 
"xmlns", 
"jabber:iq:register");
 
 3082    iks_insert_node(iq, query);
 
 3085        iks_insert_attrib(
error, 
"code", 
"406");
 
 3086        iks_insert_attrib(
error, 
"type", 
"modify");
 
 3087        iks_insert_attrib(notacceptable, 
"xmlns", 
"urn:ietf:params:xml:ns:xmpp-stanzas");
 
 3089        iks_insert_node(iq, 
error);
 
 3090        iks_insert_node(
error, notacceptable);
 
 3092        ast_log(
LOG_ERROR, 
"Received register attempt from '%s' but buddy is not configured on component '%s'\n",
 
 3093            pak->from->partial, client->
name);
 
 3094    } 
else if (!(
node = iks_find_attrib(pak->query, 
"node"))) {
 
 3095        iks_insert_cdata(instructions, 
"Welcome to Asterisk - the Open Source PBX.\n", 0);
 
 3096        iks_insert_node(query, instructions);
 
 3099        ast_log(
LOG_WARNING, 
"Received register get to component '%s' using unsupported node '%s' from '%s'\n",
 
 3100            client->
name, 
node, pak->from->partial);
 
 3106        ast_log(
LOG_WARNING, 
"Could not send response to '%s' for received register get on component '%s'\n",
 
 3107            pak->from->partial, client->
name);
 
 3111    iks_delete(instructions);
 
 3112    iks_delete(notacceptable);
 
 3117    return IKS_FILTER_EAT;
 
 
 3124    iks *iq, *presence = 
NULL, *x = 
NULL;
 
 3126    if (!(iq = iks_new(
"iq")) || !(presence = iks_new(
"presence")) || !(x = iks_new(
"x"))) {
 
 3127        ast_log(
LOG_ERROR, 
"Failed to allocate stanzas for register set response to '%s' on component '%s'\n",
 
 3128            pak->from->partial, client->
name);
 
 3132    iks_insert_attrib(iq, 
"from", client->
jid->full);
 
 3133    iks_insert_attrib(iq, 
"to", pak->from->full);
 
 3134    iks_insert_attrib(iq, 
"id", pak->id);
 
 3135    iks_insert_attrib(iq, 
"type", 
"result");
 
 3138        ast_log(
LOG_WARNING, 
"Could not send response to '%s' for received register set on component '%s'\n",
 
 3139            pak->from->partial, client->
name);
 
 3143    iks_insert_attrib(presence, 
"from", client->
jid->full);
 
 3144    iks_insert_attrib(presence, 
"to", pak->from->partial);
 
 3146    iks_insert_attrib(presence, 
"id", client->
mid);
 
 3149    iks_insert_attrib(presence, 
"type", 
"subscribe");
 
 3150    iks_insert_attrib(x, 
"xmlns", 
"vcard-temp:x:update");
 
 3152    iks_insert_node(presence, x);
 
 3156            pak->from->partial, client->
name);
 
 3161    iks_delete(presence);
 
 3164    return IKS_FILTER_EAT;
 
 
 3177        !(iq = iks_new(
"iq")) || !(query = iks_new(
"query")) || !(
item = iks_new(
"item")) || !(feature = iks_new(
"feature"))) {
 
 3178        ast_log(
LOG_ERROR, 
"Failed to allocate stanzas for service discovery items response to '%s' on component '%s'\n",
 
 3179            pak->from->partial, client->
name);
 
 3183    iks_insert_attrib(iq, 
"from", clientcfg->user);
 
 3184    iks_insert_attrib(iq, 
"to", pak->from->full);
 
 3185    iks_insert_attrib(iq, 
"id", pak->id);
 
 3186    iks_insert_attrib(iq, 
"type", 
"result");
 
 3187    iks_insert_attrib(query, 
"xmlns", 
"http://jabber.org/protocol/disco#items");
 
 3188    iks_insert_node(iq, query);
 
 3190    if (!(
node = iks_find_attrib(pak->query, 
"node"))) {
 
 3191        iks_insert_attrib(
item, 
"node", 
"http://jabber.org/protocol/commands");
 
 3192        iks_insert_attrib(
item, 
"name", 
"Asterisk Commands");
 
 3193        iks_insert_attrib(
item, 
"jid", clientcfg->user);
 
 3195        iks_insert_node(query, 
item);
 
 3196    } 
else if (!strcasecmp(
node, 
"http://jabber.org/protocol/commands")) {
 
 3197        iks_insert_attrib(query, 
"node", 
"http://jabber.org/protocol/commands");
 
 3199        ast_log(
LOG_WARNING, 
"Received service discovery items request to component '%s' using unsupported node '%s' from '%s'\n",
 
 3200            client->
name, 
node, pak->from->partial);
 
 3205        ast_log(
LOG_WARNING, 
"Could not send response to service discovery items request from '%s' on component '%s'\n",
 
 3206            pak->from->partial, client->
name);
 
 3210    iks_delete(feature);
 
 3215    return IKS_FILTER_EAT;
 
 
 3221    if (!strcmp(iks_name(
node), 
"stream:features")) {
 
 3225    if (strcmp(iks_name(
node), 
"handshake")) {
 
 
 3252    ast_debug(3, 
"XMPP client '%s' received a message\n", client->
name);
 
 3254    if (!(body = iks_find_cdata(pak->x, 
"body"))) {
 
 3307    ast_debug(3, 
"Deleted %d messages for client %s from JID %s\n", deleted, client->
name, pak->from->partial);
 
 
 3326    if (!(iq = iks_new(
"iq")) || !(query = iks_new(
"query"))) {
 
 3331    iks_insert_attrib(iq, 
"type", 
"get");
 
 3332    iks_insert_attrib(iq, 
"to", to);
 
 3333    iks_insert_attrib(iq, 
"from", from);
 
 3335    iks_insert_attrib(iq, 
"id", client->
mid);
 
 3338    iks_insert_attrib(query, 
"xmlns", 
"http://jabber.org/protocol/disco#info");
 
 3339    iks_insert_node(iq, query);
 
 
 3363    ast_debug(2, 
"JABBER: Sending Keep-Alive Ping for client '%s'\n", client->
name);
 
 3365    if (!(iq = iks_new(
"iq")) || !(ping = iks_new(
"ping"))) {
 
 3370    iks_insert_attrib(iq, 
"type", 
"get");
 
 3371    iks_insert_attrib(iq, 
"to", to);
 
 3372    iks_insert_attrib(iq, 
"from", from);
 
 3375    iks_insert_attrib(iq, 
"id", client->
mid);
 
 3379    iks_insert_attrib(ping, 
"xmlns", 
"urn:xmpp:ping");
 
 3380    iks_insert_node(iq, ping);
 
 
 3396    char *
type = iks_find_attrib(pak->x, 
"type");
 
 3406    if (!pak->from->resource) {
 
 3412        if (strcmp(client->
jid->partial, pak->from->partial)) {
 
 3413            ast_log(
LOG_WARNING, 
"Received presence information about '%s' despite not having them in roster on client '%s'\n",
 
 3414                pak->from->partial, client->
name);
 
 3425                ast_log(
LOG_ERROR, 
"Could not allocate resource object for resource '%s' of buddy '%s' on client '%s'\n",
 
 3426                    pak->from->resource, buddy->
id, client->
name);
 
 3444        if (!(
node = iks_find_attrib(iks_find(pak->x, 
"c"), 
"node"))) {
 
 3445            node = iks_find_attrib(iks_find(pak->x, 
"caps:c"), 
"node");
 
 3448        if (!(ver = iks_find_attrib(iks_find(pak->x, 
"c"), 
"ver"))) {
 
 3449            ver = iks_find_attrib(iks_find(pak->x, 
"caps:c"), 
"ver");
 
 3466            if (iks_find_with_attrib(pak->x, 
"c", 
"node", 
"http://www.google.com/xmpp/client/caps") ||
 
 3467                iks_find_with_attrib(pak->x, 
"caps:c", 
"node", 
"http://www.google.com/xmpp/client/caps") ||
 
 3468                iks_find_with_attrib(pak->x, 
"c", 
"node", 
"http://www.android.com/gtalk/client/caps") ||
 
 3469                iks_find_with_attrib(pak->x, 
"caps:c", 
"node", 
"http://www.android.com/gtalk/client/caps") ||
 
 3470                iks_find_with_attrib(pak->x, 
"c", 
"node", 
"http://mail.google.com/xmpp/client/caps") ||
 
 3471                iks_find_with_attrib(pak->x, 
"caps:c", 
"node", 
"http://mail.google.com/xmpp/client/caps")) {
 
 3477                ast_log(
LOG_WARNING, 
"Could not send discovery information request to resource '%s' of buddy '%s' on client '%s', capabilities may be incomplete\n", 
resource->resource, buddy->
id, client->
name);
 
 3483        resource->priority = atoi((iks_find_cdata(pak->x, 
"priority")) ? iks_find_cdata(pak->x, 
"priority") : 
"0");
 
 3488                  "Account: %s\r\nJID: %s\r\nResource: %s\r\nStatus: %d\r\nPriority: %d" 
 3489                  "\r\nDescription: %s\r\n",
 
 3501                  "Account: %s\r\nJID: %s\r\nStatus: %u\r\n",
 
 3502                  client->
name, pak->from->partial, pak->show ? pak->show : IKS_SHOW_UNAVAILABLE);
 
 
 3525    switch (pak->subtype) {
 
 3526    case IKS_TYPE_SUBSCRIBE:
 
 3530            if ((presence = iks_new(
"presence")) && (
status = iks_new(
"status"))) {
 
 3531                iks_insert_attrib(presence, 
"type", 
"subscribed");
 
 3532                iks_insert_attrib(presence, 
"to", pak->from->full);
 
 3533                iks_insert_attrib(presence, 
"from", client->
jid->full);
 
 3536                    iks_insert_attrib(presence, 
"id", pak->id);
 
 3539                iks_insert_cdata(
status, 
"Asterisk has approved your subscription", 0);
 
 3540                iks_insert_node(presence, 
status);
 
 3543                    ast_log(
LOG_ERROR, 
"Could not send subscription acceptance to '%s' from client '%s'\n",
 
 3544                        pak->from->partial, client->
name);
 
 3547                ast_log(
LOG_ERROR, 
"Could not allocate presence stanzas for accepting subscription from '%s' to client '%s'\n",
 
 3548                    pak->from->partial, client->
name);
 
 3552            iks_delete(presence);
 
 3559    case IKS_TYPE_SUBSCRIBED:
 
 3568                pak->from->partial, client->
name);
 
 
 3606    pak = iks_packet(
node);
 
 3611    if (iks_has_children(
node) && strchr(iks_name(iks_child(
node)), 
':')) {
 
 3612        char *node_ns = 
NULL;
 
 3614        char *node_name = iks_name(iks_child(
node));
 
 3615        char *aux = strchr(node_name, 
':') + 1;
 
 3616        snprintf(attr, strlen(
"xmlns:") + (strlen(node_name) - strlen(aux)), 
"xmlns:%s", node_name);
 
 3617        node_ns = iks_find_attrib(iks_child(
node), attr);
 
 3620            pak->query = iks_child(
node);
 
 3647    iks_filter_packet(client->
filter, pak);
 
 
 3658        pthread_cancel(client->
thread);
 
 3674    if (client->stream_flags & SECURE) {
 
 3675        SSL_shutdown(client->ssl_session);
 
 3676        SSL_CTX_free(client->ssl_context);
 
 3677        SSL_free(client->ssl_session);
 
 3680    client->stream_flags = 0;
 
 3684        iks_disconnect(client->
parser);
 
 
 3695    struct timeval tv = { .tv_sec = 5, .tv_usec = 0 };
 
 3698    int res = IKS_NET_NOCONN;
 
 3707    iks_parser_reset(client->
parser);
 
 3709    if (!client->
filter && !(client->
filter = iks_filter_new())) {
 
 3715        ast_debug(2, 
"Obtaining OAuth access token for client '%s'\n", client->
name);
 
 3722    res = iks_connect_via(client->
parser, 
S_OR(clientcfg->server, client->
jid->server), clientcfg->port,
 
 3726    setsockopt(iks_fd(client->
parser), SOL_SOCKET, SO_RCVTIMEO, (
char *)&tv,
sizeof(
struct timeval));
 
 3728    if (res == IKS_NET_NOCONN) {
 
 3729        ast_log(
LOG_ERROR, 
"No XMPP connection available when trying to connect client '%s'\n", client->
name);
 
 3731    } 
else if (res == IKS_NET_NODNS) {
 
 3732        ast_log(
LOG_ERROR, 
"No DNS available for XMPP connection when trying to connect client '%s'\n", client->
name);
 
 
 3745    struct pollfd pfd = { .events = POLLIN };
 
 3750        pfd.fd = SSL_get_fd(client->ssl_session);
 
 3756        pfd.fd = iks_fd(client->
parser);
 
 3758    res = 
ast_poll(&pfd, 1, timeout > 0 ? timeout * 1000 : -1);
 
 3762            len = SSL_read(client->ssl_session, buffer, buf_len);
 
 3765            len = recv(pfd.fd, buffer, buf_len, 0);
 
 3769        } 
else if (
len <= 0) {
 
 
 3779    int len, ret, pos = 0, newbufpos = 0;
 
 3786        if (
len < 0) 
return IKS_NET_RWERR;
 
 3798                while (isspace(
buf[pos+1])) {
 
 3802            newbuf[newbufpos] = 
c;
 
 3814            ast_debug(1, 
"JABBER: Detected Google Keep Alive. " 
 3815                "Sending out Ping request for client '%s'\n", client->
name);
 
 3823        ret = iks_parse(client->
parser, newbuf, 0, 0);
 
 3824        memset(newbuf, 0, 
sizeof(newbuf));
 
 3837        if (ret != IKS_OK) {
 
 3840        ast_debug(3, 
"XML parsing successful\n");
 
 
 3848    pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, 
NULL);
 
 3851    *sleep_time = 
MIN(60, *sleep_time * 2);
 
 3853    pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, 
NULL);
 
 
 3860    int res = IKS_NET_RWERR;
 
 3861    unsigned int sleep_time = 1;
 
 3864    pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, 
NULL);
 
 3872        if (res == IKS_NET_RWERR || client->
timeout == 0) {
 
 3876                res = IKS_NET_RWERR;
 
 3889        if (res == IKS_HOOK) {
 
 3891        } 
else if (res == IKS_NET_TLSFAIL) {
 
 3897            if (cfg && cfg->clients) {
 
 3907            if (res == IKS_OK) {
 
 3912        } 
else if (res == IKS_NET_RWERR) {
 
 3916        } 
else if (res == IKS_NET_NOSOCK) {
 
 3918        } 
else if (res == IKS_NET_NOCONN) {
 
 3920        } 
else if (res == IKS_NET_NODNS) {
 
 3922        } 
else if (res == IKS_NET_NOTSUPP) {
 
 3924        } 
else if (res == IKS_NET_DROPPED) {
 
 3926        } 
else if (res == IKS_NET_UNKNOWN) {
 
 3928        } 
else if (res == IKS_OK) {
 
 
 3956    char cBuf[1024] = 
"";
 
 3957    const char *
url = 
"https://www.googleapis.com/oauth2/v3/token";
 
 3962        "CURL(%s,client_id=%s&client_secret=%s&refresh_token=%s&grant_type=refresh_token)",
 
 3967    ast_debug(2, 
"Performing OAuth 2.0 authentication for client '%s' using command: %s\n",
 
 3971        ast_log(
LOG_ERROR, 
"CURL is unavailable. This is required for OAuth 2.0 authentication of XMPP client '%s'. Please ensure it is loaded.\n",
 
 3976    ast_debug(2, 
"OAuth 2.0 authentication for client '%s' returned: %s\n", cfg->
name, cBuf);
 
 3987    ast_log(
LOG_ERROR, 
"An error occurred while performing OAuth 2.0 authentication for client '%s': %s\n", cfg->
name, cBuf);
 
 
 4009            ast_log(
LOG_ERROR, 
"Iksemel stream could not be created for client '%s' - client not active\n", cfg->
name);
 
 4017            char resource[strlen(cfg->
user) + strlen(
"/asterisk-xmpp") + 1];
 
 4019            snprintf(resource, 
sizeof(resource), 
"%s/asterisk-xmpp", cfg->
user);
 
 4026            ast_log(
LOG_ERROR, 
"Jabber identity '%s' could not be created for client '%s' - client not active\n", cfg->
user, cfg->
name);
 
 
 4077    if (!cfg || !cfg->clients || !(clientcfg = 
xmpp_config_find(cfg->clients, jabber))) {
 
 
 4111    query = iks_insert(
request, 
"query");
 
 4112    iks_insert_attrib(query, 
"xmlns", 
"http://jabber.org/protocol/disco#items");
 
 4115        iks_insert_attrib(query, 
"node", collection);
 
 
 4132    if (iks_has_children(pak->query)) {
 
 4133        item = iks_first_tag(pak->query);
 
 4134        ast_verbose(
"Connection %s: %s\nNode name: %s\n", client->
name, client->
jid->partial,
 
 4135                iks_find_attrib(
item, 
"node"));
 
 4136        while ((
item = iks_next_tag(
item))) {
 
 4146    return IKS_FILTER_EAT;
 
 
 4159        ast_log(
LOG_ERROR, 
"Could not request pubsub nodes on client '%s' - IQ could not be created\n", client->
name);
 
 4164                IKS_PAK_IQ, IKS_RULE_SUBTYPE, IKS_TYPE_RESULT, IKS_RULE_ID, client->
mid,
 
 
 4187        e->
command = 
"xmpp list nodes";
 
 4189            "Usage: xmpp list nodes <connection> [collection]\n" 
 4190            "       Lists the user's nodes on the respective connection\n" 
 4191            "       ([connection] as configured in xmpp.conf.)\n";
 
 4197    if (
a->argc > 5 || 
a->argc < 4) {
 
 4199    } 
else if (
a->argc == 4 || 
a->argc == 5) {
 
 4204        collection = 
a->argv[4];
 
 4212    ast_cli(
a->fd, 
"Listing pubsub nodes.\n");
 
 
 4230    if (iks_has_children(pak->query)) {
 
 4231        item = iks_first_tag(pak->query);
 
 4233            iks_find_attrib(
item, 
"node"));
 
 4234        while ((
item = iks_next_tag(
item))) {
 
 4243    return IKS_FILTER_EAT;
 
 
 4251                IKS_PAK_IQ, IKS_RULE_SUBTYPE, IKS_TYPE_RESULT, IKS_RULE_ID, client->
mid,
 
 
 4273        e->
command = 
"xmpp purge nodes";
 
 4275            "Usage: xmpp purge nodes <connection> <node>\n" 
 4276            "       Purges nodes on PubSub server\n" 
 4277            "       as configured in xmpp.conf.\n";
 
 
 4318        e->
command = 
"xmpp delete node";
 
 4320            "Usage: xmpp delete node <connection> <node>\n" 
 4321            "       Deletes a node on PubSub server\n" 
 4322            "       as configured in xmpp.conf.\n";
 
 
 4351    const char *
name, *collection_name;
 
 4355        e->
command = 
"xmpp create collection";
 
 4357            "Usage: xmpp create collection <connection> <collection>\n" 
 4358            "       Creates a PubSub collection node using the account\n" 
 4359            "       as configured in xmpp.conf.\n";
 
 4369    collection_name = 
a->argv[4];
 
 4376    ast_cli(
a->fd, 
"Creating test PubSub node collection.\n");
 
 
 4391    const char *
name, *collection_name, *leaf_name;
 
 4395        e->
command = 
"xmpp create leaf";
 
 4397            "Usage: xmpp create leaf <connection> <collection> <leaf>\n" 
 4398            "       Creates a PubSub leaf node using the account\n" 
 4399            "       as configured in xmpp.conf.\n";
 
 4409    collection_name = 
a->argv[4];
 
 4410    leaf_name = 
a->argv[5];
 
 4417    ast_cli(
a->fd, 
"Creating test PubSub node collection.\n");
 
 
 4433        e->
command = 
"xmpp set debug {on|off}";
 
 4435            "Usage: xmpp set debug {on|off}\n" 
 4436            "       Enables/disables dumping of XMPP/Jabber packets for debugging purposes.\n";
 
 4442    if (
a->argc != e->
args) {
 
 4446    if (!strncasecmp(
a->argv[e->
args - 1], 
"on", 2)) {
 
 4448        ast_cli(
a->fd, 
"XMPP Debugging Enabled.\n");
 
 4450    } 
else if (!strncasecmp(
a->argv[e->
args - 1], 
"off", 3)) {
 
 4452        ast_cli(
a->fd, 
"XMPP Debugging Disabled.\n");
 
 
 4471        e->
command = 
"xmpp show connections";
 
 4473            "Usage: xmpp show connections\n" 
 4474            "       Shows state of client and component connections\n";
 
 4480    if (!cfg || !cfg->clients) {
 
 4484    ast_cli(
a->fd, 
"Jabber Users and their status:\n");
 
 4492            state = 
"Disconnecting";
 
 4495            state = 
"Disconnected";
 
 4498            state = 
"Connecting";
 
 4501            state = 
"Waiting to request TLS";
 
 4504            state = 
"Requested TLS";
 
 4507            state = 
"Waiting to authenticate";
 
 4510            state = 
"Authenticating";
 
 4513            state = 
"Retrieving roster";
 
 4516            state = 
"Connected";
 
 
 4547        e->
command = 
"xmpp show buddies";
 
 4549            "Usage: xmpp show buddies\n" 
 4550            "       Shows buddy lists of our clients\n";
 
 4556    if (!cfg || !cfg->clients) {
 
 4560    ast_cli(
a->fd, 
"XMPP buddy lists\n");
 
 4581                ast_cli(
a->fd, 
"\t\t\tGoogle Talk capable: %s\n", 
resource->caps.google ? 
"yes" : 
"no");
 
 4582                ast_cli(
a->fd, 
"\t\t\tJingle capable: %s\n", 
resource->caps.jingle ? 
"yes" : 
"no");
 
 
 4635    if (!strcasecmp(
var->name, 
"debug")) {
 
 4637    } 
else if (!strcasecmp(
var->name, 
"autoprune")) {
 
 4639    } 
else if (!strcasecmp(
var->name, 
"autoregister")) {
 
 4641    } 
else if (!strcasecmp(
var->name, 
"auth_policy")) {
 
 4643    } 
else if (!strcasecmp(
var->name, 
"collection_nodes")) {
 
 4645    } 
else if (!strcasecmp(
var->name, 
"pubsub_autocreate")) {
 
 
 4658    if (!strcasecmp(
var->name, 
"debug")) {
 
 4660    } 
else if (!strcasecmp(
var->name, 
"type")) {
 
 4662    } 
else if (!strcasecmp(
var->name, 
"distribute_events")) {
 
 4664    } 
else if (!strcasecmp(
var->name, 
"usetls")) {
 
 4666    } 
else if (!strcasecmp(
var->name, 
"usesasl")) {
 
 4668    } 
else if (!strcasecmp(
var->name, 
"forceoldssl")) {
 
 4670    } 
else if (!strcasecmp(
var->name, 
"keepalive")) {
 
 4672    } 
else if (!strcasecmp(
var->name, 
"autoprune")) {
 
 4675    } 
else if (!strcasecmp(
var->name, 
"autoregister")) {
 
 4678    } 
else if (!strcasecmp(
var->name, 
"auth_policy")) {
 
 4681    } 
else if (!strcasecmp(
var->name, 
"sendtodialplan")) {
 
 
 4694    if (!strcasecmp(
var->value, 
"unavailable")) {
 
 4695        cfg->
status = IKS_SHOW_UNAVAILABLE;
 
 4696    } 
else if (!strcasecmp(
var->value, 
"available") || !strcasecmp(
var->value, 
"online")) {
 
 4697        cfg->
status = IKS_SHOW_AVAILABLE;
 
 4698    } 
else if (!strcasecmp(
var->value, 
"chat") || !strcasecmp(
var->value, 
"chatty")) {
 
 4699        cfg->
status = IKS_SHOW_CHAT;
 
 4700    } 
else if (!strcasecmp(
var->value, 
"away")) {
 
 4701        cfg->
status = IKS_SHOW_AWAY;
 
 4702    } 
else if (!strcasecmp(
var->value, 
"xa") || !strcasecmp(
var->value, 
"xaway")) {
 
 4703        cfg->
status = IKS_SHOW_XA;
 
 4704    } 
else if (!strcasecmp(
var->value, 
"dnd")) {
 
 4705        cfg->
status = IKS_SHOW_DND;
 
 4706    } 
else if (!strcasecmp(
var->value, 
"invisible")) {
 
 4707#ifdef IKS_SHOW_INVISIBLE 
 4708        cfg->
status = IKS_SHOW_INVISIBLE;
 
 4710        cfg->
status = IKS_SHOW_DND;
 
 
 4811        ast_log(
LOG_WARNING, 
"Entity ID is not set. The distributing device state or MWI will not work.\n");
 
 
void ast_cli_unregister_multiple(void)
char * strsep(char **str, const char *delims)
Asterisk main include file. File version handling, generic pbx functions.
#define ast_strdup(str)
A wrapper for strdup()
#define ast_strdupa(s)
duplicate a string in memory from the stack
#define ast_asprintf(ret, fmt,...)
A wrapper for asprintf()
#define ast_calloc(num, len)
A wrapper for calloc()
#define ao2_iterator_next(iter)
#define AO2_GLOBAL_OBJ_STATIC(name)
Define a global object holder to be used to hold an ao2 object, statically initialized.
#define ao2_link(container, obj)
Add an object to a container.
@ AO2_ALLOC_OPT_LOCK_MUTEX
#define ao2_callback(c, flags, cb_fn, arg)
ao2_callback() is a generic function that applies cb_fn() to all objects in a container,...
int ao2_container_count(struct ao2_container *c)
Returns the number of elements in a container.
#define ao2_unlink_flags(container, obj, flags)
Remove an object from a container.
#define ao2_link_flags(container, obj, flags)
Add an object to a container.
#define ao2_global_obj_ref(holder)
Get a reference to the object stored in the global holder.
#define ao2_find(container, arg, flags)
struct ao2_iterator ao2_iterator_init(struct ao2_container *c, int flags) attribute_warn_unused_result
Create an iterator for a container.
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
#define ao2_global_obj_release(holder)
Release the ao2 object held in the global holder.
void ao2_iterator_destroy(struct ao2_iterator *iter)
Destroy a container iterator.
@ OBJ_NOLOCK
Assume that the ao2_container is already locked.
#define ao2_container_alloc_list(ao2_options, container_options, sort_fn, cmp_fn)
Allocate and initialize a list container.
#define ao2_alloc(data_size, destructor_fn)
#define ao2_container_alloc_hash(ao2_options, container_options, n_buckets, hash_fn, sort_fn, cmp_fn)
Allocate and initialize a hash container with the desired number of buckets.
static struct console_pvt globals
static int match(struct ast_sockaddr *addr, unsigned short callno, unsigned short dcallno, const struct chan_iax2_pvt *cur, int check_dcallno)
static char version[AST_MAX_EXTENSION]
static int request(void *obj)
const char * ast_channel_name(const struct ast_channel *chan)
int ast_autoservice_stop(struct ast_channel *chan)
Stop servicing a channel for us...
int ast_autoservice_start(struct ast_channel *chan)
Automatically service a channel for us...
Standard Command Line Interface.
#define AST_CLI_DEFINE(fn, txt,...)
void ast_cli(int fd, const char *fmt,...)
#define ast_cli_register_multiple(e, len)
Register multiple commands.
Configuration option-handling.
void aco_info_destroy(struct aco_info *info)
Destroy an initialized aco_info struct.
@ ACO_PROCESS_ERROR
Their was an error and no changes were applied.
#define STRFLDSET(type,...)
Convert a struct and a list of stringfield fields to an argument list of field offsets.
int aco_info_init(struct aco_info *info)
Initialize an aco_info structure.
#define FLDSET(type,...)
Convert a struct and list of fields to an argument list of field offsets.
#define aco_option_register(info, name, matchtype, types, default_val, opt_type, flags,...)
Register a config option.
@ OPT_UINT_T
Type for default option handler for unsigned integers.
@ OPT_STRINGFIELD_T
Type for default option handler for stringfields.
#define aco_option_register_custom(info, name, matchtype, types, default_val, handler, flags)
Register a config option.
#define CONFIG_INFO_STANDARD(name, arr, alloc,...)
Declare an aco_info struct with default module and preload values.
enum aco_process_status aco_process_config(struct aco_info *info, int reload)
Process a config info via the options registered with an aco_info.
#define ACO_TYPES(...)
A helper macro to ensure that aco_info types always have a sentinel.
struct stasis_message_type * ast_device_state_message_type(void)
Get the Stasis message type for device state messages.
@ AST_DEVSTATE_NOT_CACHABLE
const char * ast_devstate_str(enum ast_device_state devstate) attribute_pure
Convert device state to text string that is easier to parse.
struct stasis_cache * ast_device_state_cache(void)
Backend cache for ast_device_state_topic_cached()
int ast_devstate_changed(enum ast_device_state state, enum ast_devstate_cache cachable, const char *fmt,...)
Tells Asterisk the State for Device is changed.
struct stasis_topic * ast_device_state_topic_all(void)
Get the Stasis topic for device state messages.
enum ast_device_state ast_devstate_val(const char *val)
Convert device state from text to integer value.
ast_device_state
Device States.
int ast_publish_device_state_full(const char *device, enum ast_device_state state, enum ast_devstate_cache cachable, struct ast_eid *eid)
Publish a device state update with EID.
void ast_endpoint_set_state(struct ast_endpoint *endpoint, enum ast_endpoint_state state)
Updates the state of the given endpoint.
void ast_endpoint_shutdown(struct ast_endpoint *endpoint)
Shutsdown an ast_endpoint.
struct ast_endpoint * ast_endpoint_create(const char *tech, const char *resource)
Create an endpoint struct.
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
void astman_send_error(struct mansession *s, const struct message *m, char *error)
Send error in manager transaction.
void astman_send_ack(struct mansession *s, const struct message *m, char *msg)
Send ack in manager transaction.
const char * astman_get_header(const struct message *m, char *var)
Get header from manager transaction.
void astman_append(struct mansession *s, const char *fmt,...)
int ast_manager_unregister(const char *action)
Unregister a registered manager command.
Application convenience functions, designed to give consistent look and feel to Asterisk apps.
#define AST_APP_ARG(name)
Define an application argument.
#define AST_DECLARE_APP_ARGS(name, arglist)
Declare a structure to hold an application's arguments.
#define AST_STANDARD_APP_ARGS(args, parse)
Performs the 'standard' argument separation process for an application.
#define AST_NONSTANDARD_APP_ARGS(args, parse, sep)
Performs the 'nonstandard' argument separation process for an application.
#define ast_debug(level,...)
Log a DEBUG message.
Asterisk JSON abstraction layer.
void ast_json_unref(struct ast_json *value)
Decrease refcount on value. If refcount reaches zero, value is freed.
struct ast_json * ast_json_load_string(const char *input, struct ast_json_error *error)
Parse null terminated string into a JSON object or array.
const char * ast_json_string_get(const struct ast_json *string)
Get the value of a JSON string.
struct ast_json * ast_json_object_get(struct ast_json *object, const char *key)
Get a field from a JSON object.
#define AST_LIST_HEAD_DESTROY(head)
Destroys a list head structure.
#define AST_LIST_EMPTY(head)
Checks whether the specified list contains any entries.
#define AST_LIST_HEAD_INIT(head)
Initializes a list head structure.
#define AST_LIST_TRAVERSE_SAFE_END
Closes a safe loop traversal block.
#define AST_LIST_LOCK(head)
Locks a list.
#define AST_LIST_INSERT_HEAD(head, elm, field)
Inserts a list entry at the head of a list.
#define AST_LIST_TRAVERSE_SAFE_BEGIN(head, var, field)
Loops safely over (traverses) the entries in a list.
#define AST_LIST_REMOVE_CURRENT(field)
Removes the current entry from a list during a traversal.
#define AST_LIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
#define ast_cond_destroy(cond)
#define AST_PTHREADT_NULL
#define ast_cond_init(cond, attr)
#define ast_cond_timedwait(cond, mutex, time)
#define ast_mutex_init(pmutex)
#define ast_mutex_unlock(a)
#define ast_cond_broadcast(cond)
pthread_cond_t ast_cond_t
#define ast_mutex_destroy(a)
#define ast_mutex_lock(a)
The AMI - Asterisk Manager Interface - is a TCP protocol created to manage Asterisk with third-party ...
#define manager_event(category, event, contents,...)
External routines may send asterisk manager events this way.
#define EVENT_FLAG_SYSTEM
#define ast_manager_register_xml(action, authority, func)
Register a manager callback using XML documentation to describe the manager.
Out-of-call text message support.
int ast_msg_set_from(struct ast_msg *msg, const char *fmt,...)
Set the 'from' URI of a message.
struct ast_msg * ast_msg_destroy(struct ast_msg *msg)
Destroy an ast_msg.
int ast_msg_set_endpoint(struct ast_msg *msg, const char *fmt,...)
Set the technology's endpoint associated with this message.
int ast_msg_set_tech(struct ast_msg *msg, const char *fmt,...)
Set the technology associated with this message.
struct ast_msg * ast_msg_alloc(void)
Allocate a message.
int ast_msg_tech_unregister(const struct ast_msg_tech *tech)
Unregister a message technology.
int ast_msg_set_var(struct ast_msg *msg, const char *name, const char *value)
Set a variable on the message going to the dialplan.
int ast_msg_tech_register(const struct ast_msg_tech *tech)
Register a message technology.
const char * ast_msg_get_body(const struct ast_msg *msg)
Get the body of a message.
int ast_msg_set_context(struct ast_msg *msg, const char *fmt,...)
Set the dialplan context for this message.
int ast_msg_set_body(struct ast_msg *msg, const char *fmt,...)
Set the 'body' text of a message (in UTF-8)
int ast_msg_set_to(struct ast_msg *msg, const char *fmt,...)
Set the 'to' URI of a message.
int ast_msg_queue(struct ast_msg *msg)
Queue a message for routing through the dialplan.
Asterisk module definitions.
@ AST_MODFLAG_GLOBAL_SYMBOLS
#define AST_MODULE_INFO(keystr, flags_to_set, desc, fields...)
@ AST_MODPRI_CHANNEL_DEPEND
@ AST_MODULE_SUPPORT_CORE
#define ASTERISK_GPL_KEY
The text the key() function should return.
int ast_unregister_application(const char *app)
Unregister an application.
@ AST_MODULE_LOAD_SUCCESS
@ AST_MODULE_LOAD_DECLINE
Module has failed to load, may be in an inconsistent state.
#define ast_register_application_xml(app, execute)
Register an application using XML documentation.
struct stasis_message_type * ast_mwi_state_type(void)
Get the Stasis Message Bus API message type for MWI messages.
int ast_publish_mwi_state_full(const char *mailbox, const char *context, int new_msgs, int old_msgs, const char *channel_id, struct ast_eid *eid)
Publish a MWI state update via stasis with all parameters.
struct stasis_topic * ast_mwi_topic_all(void)
Get the Stasis Message Bus API topic for MWI messages.
#define ast_custom_function_register(acf)
Register a custom function.
int ast_custom_function_unregister(struct ast_custom_function *acf)
Unregister a custom function.
int ast_func_read(struct ast_channel *chan, const char *function, char *workspace, size_t len)
executes a read operation on a function
#define ast_poll(a, b, c)
static struct agi_command commands[]
AGI commands list.
static struct stasis_subscription * sub
Statsd channel stats. Exmaple of how to subscribe to Stasis events.
struct ao2_container * container
static int unsubscribe(void *obj, void *arg, int flags)
static int xmpp_buddy_cmp(void *obj, void *arg, int flags)
Comparator function for XMPP buddy.
static void xmpp_pubsub_purge_nodes(struct ast_xmpp_client *client, const char *collection_name)
int ast_xmpp_client_send(struct ast_xmpp_client *client, iks *stanza)
Send an XML stanza out using an established XMPP client connection.
struct aco_type * global_options[]
static int xmpp_client_requested_tls(struct ast_xmpp_client *client, struct ast_xmpp_client_config *cfg, int type, iks *node)
Internal function called when we receive a response to our TLS initiation request.
static int delete_old_messages(struct ast_xmpp_client *client, char *from)
static void * ast_xmpp_client_config_alloc(const char *cat)
Allocator function for configuration.
static int xmpp_resource_immediate(void *obj, void *arg, int flags)
Internal astobj2 callback function which returns the first resource, which is the highest priority on...
static int xmpp_send_exec(struct ast_channel *chan, const char *data)
static const char * app_ajijoin
static int global_bitfield_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
static struct ast_custom_function jabberstatus_function
static iks * xmpp_pubsub_iq_create(struct ast_xmpp_client *client, const char *type)
Create an IQ packet.
static const char * app_ajisendgroup
static char * xmpp_cli_purge_pubsub_nodes(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Method to purge PubSub nodes via CLI.
void ast_xmpp_client_unref(struct ast_xmpp_client *client)
Release XMPP client connection reference.
static int xmpp_client_config_merge_buddies(void *obj, void *arg, int flags)
static int xmpp_client_service_discovery_get_hook(void *data, ikspak *pak)
Hook function called when client receives a service discovery get message.
int ast_xmpp_chatroom_send(struct ast_xmpp_client *client, const char *nickname, const char *address, const char *message)
Send a message to an XMPP multi-user chatroom.
static char * xmpp_do_set_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
int ast_xmpp_client_send_message(struct ast_xmpp_client *client, const char *user, const char *message)
Send a message to a given user using an established XMPP client connection.
static void xmpp_config_post_apply(void)
static int xmpp_client_authenticate_digest(struct ast_xmpp_client *client, struct ast_xmpp_client_config *cfg, int type, iks *node)
Internal function called when we need to authenticate using non-SASL.
#define RESOURCE_BUCKETS
Number of buckets for resources (per buddy)
static int xmpp_pak_s10n(struct ast_xmpp_client *client, struct ast_xmpp_client_config *cfg, iks *node, ikspak *pak)
Internal function called when a subscription message is received.
void ast_xmpp_client_unlock(struct ast_xmpp_client *client)
Unlock an XMPP client connection.
static struct ast_xmpp_client * xmpp_client_alloc(const char *name)
Allocator function for ast_xmpp_client.
static int xmpp_client_unsubscribe_user(struct ast_xmpp_client *client, const char *user)
Helper function which unsubscribes a user and removes them from the roster.
static int xmpp_client_reconnect(struct ast_xmpp_client *client)
Internal function used to reconnect an XMPP client to its server.
static iks * xmpp_pubsub_build_node_request(struct ast_xmpp_client *client, const char *collection)
Build the a node request.
static int xmpp_send_stream_header(struct ast_xmpp_client *client, const struct ast_xmpp_client_config *cfg, const char *to)
Helper function which sends an XMPP stream header to the server.
static int xmpp_pak_message(struct ast_xmpp_client *client, struct ast_xmpp_client_config *cfg, iks *node, ikspak *pak)
Internal function called when a message is received.
static int xmpp_resource_cmp(void *obj, void *arg, int flags)
Comparator function for XMPP resource.
static int xmpp_component_authenticate(struct ast_xmpp_client *client, struct ast_xmpp_client_config *cfg, int type, iks *node)
Internal function called when we should authenticate as a component.
static char * xmpp_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 int xmpp_client_authenticate_sasl(struct ast_xmpp_client *client, struct ast_xmpp_client_config *cfg, int type, iks *node)
Internal function called when we need to authenticate using SASL.
static int xmpp_client_send_raw_message(struct ast_xmpp_client *client, const char *message)
Internal function which sends a raw message.
static int xmpp_client_config_post_apply(void *obj, void *arg, int flags)
struct aco_type * client_options[]
#define BUDDY_NOT_IN_ROSTER
static int client_bitfield_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
static ast_mutex_t messagelock
static int manager_jabber_send(struct mansession *s, const struct message *m)
static int get_buddy_status(struct ast_xmpp_client_config *clientcfg, char *screenname, char *resource)
static int xmpp_join_exec(struct ast_channel *chan, const char *data)
Application to join a chat room.
static int xmpp_pak_presence(struct ast_xmpp_client *client, struct ast_xmpp_client_config *cfg, iks *node, ikspak *pak)
Internal function called when a presence message is received.
static const char * app_ajileave
static void xmpp_pubsub_subscribe(struct ast_xmpp_client *client, const char *node)
Subscribe to a PubSub node.
int ast_xmpp_chatroom_leave(struct ast_xmpp_client *client, const char *room, const char *nickname)
Leave an XMPP multi-user chatroom.
static void xmpp_pubsub_publish_device_state(struct ast_xmpp_client *client, const char *device, const char *device_state, unsigned int cachable)
Publish device state to a PubSub node.
int ast_xmpp_chatroom_invite(struct ast_xmpp_client *client, const char *user, const char *room, const char *message)
Invite a user to an XMPP multi-user chatroom.
void ast_xmpp_increment_mid(char *mid)
Helper function which increments the message identifier.
static iks * xmpp_pubsub_build_publish_skeleton(struct ast_xmpp_client *client, const char *node, const char *event_type, unsigned int cachable)
Build the skeleton of a publish.
static void * xmpp_config_find(struct ao2_container *tmp_container, const char *category)
Find function for configuration.
static int xmpp_pubsub_delete_node_list(void *data, ikspak *pak)
Delete pubsub item lists.
static void xmpp_pubsub_create_collection(struct ast_xmpp_client *client, const char *collection_name)
Create a PubSub collection node.
static int fetch_access_token(struct ast_xmpp_client_config *cfg)
static void xmpp_pubsub_devstate_cb(void *data, struct stasis_subscription *sub, struct stasis_message *msg)
Callback function for device state events.
static int xmpp_client_send_message(struct ast_xmpp_client *client, int group, const char *nick, const char *address, const char *message)
Internal function used to send a message to a user or chatroom.
static int xmpp_component_authenticating(struct ast_xmpp_client *client, struct ast_xmpp_client_config *cfg, int type, iks *node)
Internal function called when we authenticated as a component.
static void xmpp_pubsub_unsubscribe(struct ast_xmpp_client *client, const char *node)
Unsubscribe from a PubSub node.
static int xmpp_roster_hook(void *data, ikspak *pak)
Hook function called when roster is received from server.
static void sleep_with_backoff(unsigned int *sleep_time)
static void xmpp_client_destructor(void *obj)
Destructor callback function for XMPP client.
static const char * app_ajisend
static struct ast_cli_entry xmpp_cli[]
static void xmpp_pubsub_delete_node(struct ast_xmpp_client *client, const char *node_name)
Delete a PubSub node.
static char * xmpp_cli_list_pubsub_nodes(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Method to expose PubSub node list via CLI.
static int xmpp_config_prelink(void *newitem)
static int xmpp_resource_hash(const void *obj, const int flags)
Hashing function for XMPP resource.
static void xmpp_pubsub_mwi_cb(void *data, struct stasis_subscription *sub, struct stasis_message *msg)
Callback function for MWI events.
static int client_buddy_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
static int xmpp_component_register_get_hook(void *data, ikspak *pak)
Hook function called when the component is queried about registration.
void ast_xmpp_client_lock(struct ast_xmpp_client *client)
Lock an XMPP client connection.
static char * xmpp_show_clients(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static void xmpp_pubsub_create_leaf(struct ast_xmpp_client *client, const char *collection_name, const char *leaf_name)
Create a PubSub leaf node.
static void xmpp_client_set_presence(struct ast_xmpp_client *client, const char *to, const char *from, int level, const char *desc)
Internal function which changes the presence status of an XMPP client.
struct ast_xmpp_client * ast_xmpp_client_find(const char *name)
Find an XMPP client connection using a given name.
static void xmpp_init_event_distribution(struct ast_xmpp_client *client)
Initialize collections for event distribution.
static const char * app_ajistatus
static struct ast_custom_function jabberreceive_function
static int xmpp_connect_hook(void *data, ikspak *pak)
Hook function called when client finishes authenticating with the server.
static void * xmpp_config_alloc(void)
Allocator for XMPP configuration.
static char * xmpp_cli_create_collection(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Method to expose PubSub collection node creation via CLI.
static int cached_devstate_cb(void *obj, void *arg, int flags)
struct aco_file res_xmpp_conf
static int xmpp_pubsub_receive_node_list(void *data, ikspak *pak)
Receive pubsub item lists.
static int xmpp_client_service_discovery_result_hook(void *data, ikspak *pak)
Hook function called when client receives a service discovery result message.
static int xmpp_component_service_discovery_items_hook(void *data, ikspak *pak)
Hook function called when we receive a service discovery items request.
static int xmpp_resource_is_available(void *obj, void *arg, int flags)
Callback function which returns when the resource is available.
#define BUDDY_BUCKETS
Number of buckets for buddies (per client)
static int xmpp_pubsub_handle_error(void *data, ikspak *pak)
static void xmpp_buddy_destructor(void *obj)
Destructor callback function for XMPP buddy.
static int xmpp_ping_request(struct ast_xmpp_client *client, const char *to, const char *from)
Helper function which sends a ping request to a server.
static struct aco_type client_option
static char * xmpp_show_buddies(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static iks * xmpp_pubsub_build_node_config(iks *pubsub, const char *node_type, const char *collection_name)
#define STATUS_DISAPPEAR
Status for a disappearing buddy.
static int xmpp_component_service_discovery_get_hook(void *data, ikspak *pak)
Hook function called when component receives a service discovery get message.
static int xmpp_io_recv(struct ast_xmpp_client *client, char *buffer, size_t buf_len, int timeout)
Internal function which polls on an XMPP client and receives data.
int ast_xmpp_client_disconnect(struct ast_xmpp_client *client)
Disconnect an XMPP client connection.
static void xmpp_message_destroy(struct ast_xmpp_message *message)
Destroy function for XMPP messages.
static void * xmpp_client_thread(void *data)
XMPP client connection thread.
static int load_module(void)
Load the module.
static int debug
Global debug status.
static struct ast_xmpp_buddy * xmpp_client_create_buddy(struct ao2_container *container, const char *id)
Internal function which creates a buddy on a client.
static void xmpp_pubsub_request_nodes(struct ast_xmpp_client *client, const char *collection)
Request item list from pubsub.
static int acf_jabberstatus_read(struct ast_channel *chan, const char *name, char *data, char *buf, size_t buflen)
static void xmpp_client_change_state(struct ast_xmpp_client *client, int state)
Internal function which changes the XMPP client state.
static void xmpp_pubsub_create_node(struct ast_xmpp_client *client, const char *node_type, const char *name, const char *collection_name)
Create a pubsub node.
static void xmpp_config_destructor(void *obj)
Destructor for XMPP configuration.
static int unload_module(void)
static int xmpp_send_cb(const struct ast_msg *msg, const char *to, const char *from)
static int xmpp_client_subscribe_user(void *obj, void *arg, int flags)
Callback function which subscribes to a user if needed.
static void xmpp_pubsub_create_affiliations(struct ast_xmpp_client *client, const char *node)
Add Owner affiliations for pubsub node.
static int xmpp_component_register_set_hook(void *data, ikspak *pak)
Hook function called when someone registers to the component.
int ast_xmpp_chatroom_join(struct ast_xmpp_client *client, const char *room, const char *nickname)
Join an XMPP multi-user chatroom.
static const struct xmpp_state_handler xmpp_state_handlers[]
static const struct xmpp_pak_handler xmpp_pak_handlers[]
static int xmpp_client_receive(struct ast_xmpp_client *client, unsigned int timeout)
Internal function which receives data from the XMPP client connection.
static const struct ast_msg_tech msg_tech
static int xmpp_client_set_group_presence(struct ast_xmpp_client *client, const char *room, int level, const char *nick)
static int xmpp_client_request_tls(struct ast_xmpp_client *client, struct ast_xmpp_client_config *cfg, int type, iks *node)
Internal function called when we need to request TLS support.
static int xmpp_is_secure(struct ast_xmpp_client *client)
Helper function which returns whether an XMPP client connection is secure or not.
static int client_status_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
static int xmpp_client_authenticating(struct ast_xmpp_client *client, struct ast_xmpp_client_config *cfg, int type, iks *node)
Internal function called when we are authenticating.
static int xmpp_action_hook(void *data, int type, iks *node)
Action hook for when things occur.
static struct aco_type global_option
static int xmpp_config_cmp(void *obj, void *arg, int flags)
Comparator function for configuration.
static int xmpp_client_authenticate(struct ast_xmpp_client *client, struct ast_xmpp_client_config *cfg, int type, iks *node)
Internal function called when we need to authenticate.
static int xmpp_leave_exec(struct ast_channel *chan, const char *data)
Application to leave a chat room.
static void * xmpp_client_find_or_create(const char *category)
Look up existing client or create a new one.
static int xmpp_sendgroup_exec(struct ast_channel *chan, const char *data)
Application to send a message to a groupchat.
static void xmpp_log_hook(void *data, const char *xmpp, size_t size, int incoming)
Logging hook function.
static char * xmpp_cli_delete_pubsub_node(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Method to expose PubSub node deletion via CLI.
static int acf_jabberreceive_read(struct ast_channel *chan, const char *name, char *data, char *buf, size_t buflen)
static void xmpp_resource_destructor(void *obj)
Destructor callback function for XMPP resource.
static int xmpp_pubsub_handle_event(void *data, ikspak *pak)
Callback for handling PubSub events.
static void ast_xmpp_client_config_destructor(void *obj)
Destructor function for configuration.
static int xmpp_client_send_disco_info_request(struct ast_xmpp_client *client, const char *to, const char *from)
Helper function which sends a discovery information request to a user.
static int xmpp_buddy_hash(const void *obj, const int flags)
Hashing function for XMPP buddy.
static ast_cond_t message_received_condition
static void xmpp_pubsub_publish_mwi(struct ast_xmpp_client *client, const char *mailbox, const char *oldmsgs, const char *newmsgs)
Publish MWI to a PubSub node.
struct ao2_container * stasis_cache_dump(struct stasis_cache *cache, struct stasis_message_type *type)
Dump cached items to a subscription for the ast_eid_default entity.
@ STASIS_SUBSCRIPTION_FILTER_SELECTIVE
int stasis_subscription_accept_message_type(struct stasis_subscription *subscription, const struct stasis_message_type *type)
Indicate to a subscription that we are interested in a message type.
int stasis_subscription_set_filter(struct stasis_subscription *subscription, enum stasis_subscription_message_filter filter)
Set the message type filtering level on a subscription.
#define stasis_subscribe_pool(topic, callback, data)
void * stasis_message_data(const struct stasis_message *msg)
Get the data contained in a message.
struct stasis_subscription * stasis_unsubscribe_and_join(struct stasis_subscription *subscription)
Cancel a subscription, blocking until the last message is processed.
struct stasis_subscription * stasis_unsubscribe(struct stasis_subscription *subscription)
Cancel a subscription.
int stasis_subscription_is_subscribed(const struct stasis_subscription *sub)
Returns whether a subscription is currently subscribed.
#define stasis_subscribe(topic, callback, data)
#define AST_DECLARE_STRING_FIELDS(field_list)
Declare the fields needed in a structure.
#define AST_STRING_FIELD(name)
Declare a string field.
#define ast_string_field_set(x, field, data)
Set a field to a simple string value.
#define ast_string_field_init(x, size)
Initialize a field pool and fields.
#define ast_string_field_free_memory(x)
free all memory - to be called before destroying the object
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one.
static force_inline int attribute_pure ast_str_hash(const char *str)
Compute a hash value on a string.
int attribute_pure ast_true(const char *val)
Make sure something is true. Determine if a string containing a boolean value is "true"....
static force_inline int attribute_pure ast_strlen_zero(const char *s)
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
The representation of a single configuration file to be processed.
Type information about a category-level configurable object.
When we need to walk through a container, we use an ao2_iterator to keep track of the current positio...
Main Channel structure associated with a channel.
descriptor for a cli entry.
int args
This gets set in ast_cli_register()
Data structure associated with a custom dialplan function.
The structure that contains device state.
enum ast_device_state state
const struct ast_eid * eid
The EID of the server where this message originated.
enum ast_devstate_cache cachable
An Entity ID is essentially a MAC address, brief and unique.
Structure used to handle boolean flags.
JSON parsing error information.
Abstract JSON element (object, array, string, int, ...).
const char *const name
Name of this message technology.
Structure for mutex and tracking information.
The structure that contains MWI state.
const ast_string_field uniqueid
Structure for variables, used for configurations and for channel variables.
struct ao2_container * resources
XMPP Client Configuration.
const ast_string_field server
const ast_string_field oauth_clientid
const ast_string_field oauth_secret
struct ao2_container * buddies
const ast_string_field password
const ast_string_field user
const ast_string_field context
struct ast_xmpp_client * client
const ast_string_field statusmsg
const ast_string_field pubsubnode
const ast_string_field name
const ast_string_field refresh_token
struct ast_flags mod_flags
struct stasis_subscription * mwi_sub
struct ao2_container * buddies
struct ast_endpoint * endpoint
struct ast_xmpp_client::@311 messages
struct stasis_subscription * device_state_sub
const ast_string_field name
XMPP Global Configuration.
struct ast_xmpp_message::@310 list
char resource[XMPP_MAX_RESJIDLEN]
In case you didn't read that giant block of text above the mansession_session struct,...
structure to hold users read from phoneprov_users.conf
struct ao2_container * clients
struct ast_xmpp_global_config * global
Defined handlers for different PAK types.
int(* handler)(struct ast_xmpp_client *client, struct ast_xmpp_client_config *cfg, iks *node, ikspak *pak)
Defined handlers for XMPP client states.
int(* handler)(struct ast_xmpp_client *client, struct ast_xmpp_client_config *cfg, int type, iks *node)
static void handler(const char *name, int response_code, struct ast_variable *get_params, struct ast_variable *path_vars, struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
static struct aco_type global
static struct aco_type item
int64_t ast_tvdiff_sec(struct timeval end, struct timeval start)
Computes the difference (in seconds) between two struct timeval instances.
struct timeval ast_tvadd(struct timeval a, struct timeval b)
Returns the sum of two timevals a + b.
int64_t ast_tvdiff_ms(struct timeval end, struct timeval start)
Computes the difference (in milliseconds) between two struct timeval instances.
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
struct timeval ast_tv(ast_time_t sec, ast_suseconds_t usec)
Returns a timeval from sec, usec.
int error(const char *format,...)
#define ast_test_flag(p, flag)
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
int ast_eid_cmp(const struct ast_eid *eid1, const struct ast_eid *eid2)
Compare two EIDs.
int ast_base64encode(char *dst, const unsigned char *src, int srclen, int max)
Encode data in base64.
#define ast_pthread_create_background(a, b, c, d)
#define ast_set2_flag(p, value, flag)
char * ast_eid_to_str(char *s, int maxlen, struct ast_eid *eid)
Convert an EID to a string.
int ast_eid_is_empty(const struct ast_eid *eid)
Check if EID is empty.
#define ast_copy_flags(dest, src, flagz)
struct ast_eid ast_eid_default
Global EID.
int ast_str_to_eid(struct ast_eid *eid, const char *s)
Convert a string into an EID.
void ast_sha1_hash(char *output, const char *input)
Produces SHA1 hash based on input string.
#define XMPP_MAX_RESJIDLEN
Maximum size of a resource JID.
#define XMPP_MAX_ATTRLEN
Maximum size of an attribute.
@ XMPP_STATE_AUTHENTICATE
@ XMPP_STATE_DISCONNECTED
@ XMPP_STATE_REQUESTED_TLS
@ XMPP_STATE_DISCONNECTING
@ XMPP_STATE_AUTHENTICATING