summaryrefslogtreecommitdiff
path: root/channels
diff options
context:
space:
mode:
authorJoshua Colp <jcolp@digium.com>2013-06-22 12:40:16 +0000
committerJoshua Colp <jcolp@digium.com>2013-06-22 12:40:16 +0000
commit94ec267888e907862cab6c5e24163ca3a9a72070 (patch)
tree7fd73b66642e77ca85e09c397775cab1b62e11e8 /channels
parent1267c91315f6850483022b4535beadbc0069b22e (diff)
Migrate PeerStatus events to stasis, add stasis endpoints, and add chan_pjsip device state.
(closes issue ASTERISK-21489) (closes issue ASTERISK-21503) Review: https://reviewboard.asterisk.org/r/2601/ git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@392538 65c4cc65-6c06-0410-ace0-fbb531ad65f3
Diffstat (limited to 'channels')
-rw-r--r--channels/chan_gulp.c78
-rw-r--r--channels/chan_iax2.c50
-rw-r--r--channels/chan_sip.c104
-rw-r--r--channels/chan_skinny.c31
4 files changed, 204 insertions, 59 deletions
diff --git a/channels/chan_gulp.c b/channels/chan_gulp.c
index 967349e0b..9e939a0f4 100644
--- a/channels/chan_gulp.c
+++ b/channels/chan_gulp.c
@@ -53,6 +53,8 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/musiconhold.h"
#include "asterisk/causes.h"
#include "asterisk/taskprocessor.h"
+#include "asterisk/stasis_endpoints.h"
+#include "asterisk/stasis_channels.h"
#include "asterisk/res_sip.h"
#include "asterisk/res_sip_session.h"
@@ -82,6 +84,8 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
static const char desc[] = "Gulp SIP Channel";
static const char channel_type[] = "Gulp";
+static unsigned int chan_idx;
+
/*!
* \brief Positions of various media
*/
@@ -125,6 +129,7 @@ static struct ast_frame *gulp_read(struct ast_channel *ast);
static int gulp_write(struct ast_channel *ast, struct ast_frame *f);
static int gulp_indicate(struct ast_channel *ast, int condition, const void *data, size_t datalen);
static int gulp_fixup(struct ast_channel *oldchan, struct ast_channel *newchan);
+static int gulp_devicestate(const char *data);
/*! \brief PBX interface structure for channel registration */
static struct ast_channel_tech gulp_tech = {
@@ -143,6 +148,7 @@ static struct ast_channel_tech gulp_tech = {
.exception = gulp_read,
.indicate = gulp_indicate,
.fixup = gulp_fixup,
+ .devicestate = gulp_devicestate,
.properties = AST_CHAN_TP_WANTSJITTER | AST_CHAN_TP_CREATESJITTER
};
@@ -422,8 +428,8 @@ static struct ast_channel *gulp_new(struct ast_sip_session *session, int state,
return NULL;
}
- if (!(chan = ast_channel_alloc(1, state, S_OR(session->id.number.str, ""), S_OR(session->id.name.str, ""), "", "", "", linkedid, 0, "Gulp/%s-%.*s", ast_sorcery_object_get_id(session->endpoint),
- (int)session->inv_session->dlg->call_id->id.slen, session->inv_session->dlg->call_id->id.ptr))) {
+ if (!(chan = ast_channel_alloc(1, state, S_OR(session->id.number.str, ""), S_OR(session->id.name.str, ""), "", "", "", linkedid, 0, "Gulp/%s-%08x", ast_sorcery_object_get_id(session->endpoint),
+ ast_atomic_fetchadd_int((int *)&chan_idx, +1)))) {
ao2_cleanup(pvt);
return NULL;
}
@@ -461,6 +467,8 @@ static struct ast_channel *gulp_new(struct ast_sip_session *session, int state,
ast_channel_exten_set(chan, S_OR(exten, "s"));
ast_channel_priority_set(chan, 1);
+ ast_endpoint_add_channel(session->endpoint->persistent, chan);
+
return chan;
}
@@ -623,6 +631,68 @@ static int gulp_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
return 0;
}
+/*! \brief Function called to get the device state of an endpoint */
+static int gulp_devicestate(const char *data)
+{
+ RAII_VAR(struct ast_sip_endpoint *, endpoint, ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "endpoint", data), ao2_cleanup);
+ enum ast_device_state state = AST_DEVICE_UNKNOWN;
+ RAII_VAR(struct ast_endpoint_snapshot *, endpoint_snapshot, NULL, ao2_cleanup);
+ RAII_VAR(struct stasis_caching_topic *, caching_topic, NULL, ao2_cleanup);
+ struct ast_devstate_aggregate aggregate;
+ int num, inuse = 0;
+
+ if (!endpoint) {
+ return AST_DEVICE_INVALID;
+ }
+
+ endpoint_snapshot = ast_endpoint_latest_snapshot(ast_endpoint_get_tech(endpoint->persistent),
+ ast_endpoint_get_resource(endpoint->persistent), 1);
+
+ if (endpoint_snapshot->state == AST_ENDPOINT_OFFLINE) {
+ state = AST_DEVICE_UNAVAILABLE;
+ } else if (endpoint_snapshot->state == AST_ENDPOINT_ONLINE) {
+ state = AST_DEVICE_NOT_INUSE;
+ }
+
+ if (!endpoint_snapshot->num_channels || !(caching_topic = ast_channel_topic_all_cached())) {
+ return state;
+ }
+
+ ast_devstate_aggregate_init(&aggregate);
+
+ ao2_ref(caching_topic, +1);
+
+ for (num = 0; num < endpoint_snapshot->num_channels; num++) {
+ RAII_VAR(struct stasis_message *, msg, stasis_cache_get_extended(caching_topic, ast_channel_snapshot_type(),
+ endpoint_snapshot->channel_ids[num], 1), ao2_cleanup);
+ struct ast_channel_snapshot *snapshot;
+
+ if (!msg) {
+ continue;
+ }
+
+ snapshot = stasis_message_data(msg);
+
+ if (snapshot->state == AST_STATE_DOWN) {
+ ast_devstate_aggregate_add(&aggregate, AST_DEVICE_NOT_INUSE);
+ } else if (snapshot->state == AST_STATE_RINGING) {
+ ast_devstate_aggregate_add(&aggregate, AST_DEVICE_RINGING);
+ } else if ((snapshot->state == AST_STATE_UP) || (snapshot->state == AST_STATE_RING) ||
+ (snapshot->state == AST_STATE_BUSY)) {
+ ast_devstate_aggregate_add(&aggregate, AST_DEVICE_INUSE);
+ inuse++;
+ }
+ }
+
+ if (endpoint->devicestate_busy_at && (inuse == endpoint->devicestate_busy_at)) {
+ state = AST_DEVICE_BUSY;
+ } else if (ast_devstate_aggregate_result(&aggregate) != AST_DEVICE_INVALID) {
+ state = ast_devstate_aggregate_result(&aggregate);
+ }
+
+ return state;
+}
+
struct indicate_data {
struct ast_sip_session *session;
int condition;
@@ -731,6 +801,7 @@ static int gulp_indicate(struct ast_channel *ast, int condition, const void *dat
} else {
res = -1;
}
+ ast_devstate_changed(AST_DEVICE_UNKNOWN, AST_DEVSTATE_CACHABLE, "Gulp/%s", ast_sorcery_object_get_id(session->endpoint));
break;
case AST_CONTROL_BUSY:
if (ast_channel_state(ast) != AST_STATE_UP) {
@@ -1326,7 +1397,7 @@ static int gulp_incoming_request(struct ast_sip_session *session, struct pjsip_r
return 0;
}
- if (!(session->channel = gulp_new(session, AST_STATE_DOWN, session->exten, NULL, NULL, NULL))) {
+ if (!(session->channel = gulp_new(session, AST_STATE_RING, session->exten, NULL, NULL, NULL))) {
if (pjsip_inv_end_session(session->inv_session, 503, NULL, &packet) == PJ_SUCCESS) {
ast_sip_session_send_response(session, packet);
}
@@ -1335,7 +1406,6 @@ static int gulp_incoming_request(struct ast_sip_session *session, struct pjsip_r
return -1;
}
- ast_setstate(session->channel, AST_STATE_RING);
res = ast_pbx_start(session->channel);
switch (res) {
diff --git a/channels/chan_iax2.c b/channels/chan_iax2.c
index 486af52a7..0f5c8fc2b 100644
--- a/channels/chan_iax2.c
+++ b/channels/chan_iax2.c
@@ -101,6 +101,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/data.h"
#include "asterisk/netsock2.h"
#include "asterisk/security_events.h"
+#include "asterisk/stasis_endpoints.h"
#include "asterisk/bridging.h"
#include "iax2/include/iax2.h"
@@ -552,6 +553,8 @@ struct iax2_peer {
struct ast_acl_list *acl;
enum calltoken_peer_enum calltoken_required; /*!< Is calltoken validation required or not, can be YES, NO, or AUTO */
+
+ struct ast_endpoint *endpoint; /*!< Endpoint structure for this peer */
};
#define IAX2_TRUNK_PREFACE (sizeof(struct iax_frame) + sizeof(struct ast_iax2_meta_hdr) + sizeof(struct ast_iax2_meta_trunk_hdr))
@@ -8563,6 +8566,7 @@ static void unlink_peer(struct iax2_peer *peer)
static void __expire_registry(const void *data)
{
struct iax2_peer *peer = (struct iax2_peer *) data;
+ RAII_VAR(struct ast_json *, blob, NULL, ast_json_unref);
if (!peer)
return;
@@ -8576,7 +8580,11 @@ static void __expire_registry(const void *data)
ast_debug(1, "Expiring registration for peer '%s'\n", peer->name);
if (ast_test_flag64((&globalflags), IAX_RTUPDATE) && (ast_test_flag64(peer, IAX_TEMPONLY|IAX_RTCACHEFRIENDS)))
realtime_update_peer(peer->name, &peer->addr, 0);
- manager_event(EVENT_FLAG_SYSTEM, "PeerStatus", "ChannelType: IAX2\r\nPeer: IAX2/%s\r\nPeerStatus: Unregistered\r\nCause: Expired\r\n", peer->name);
+ ast_endpoint_set_state(peer->endpoint, AST_ENDPOINT_OFFLINE);
+ blob = ast_json_pack("{s: s, s: s}",
+ "peer_status", "Unregistered",
+ "cause", "Expired");
+ ast_endpoint_blob_publish(peer->endpoint, ast_endpoint_state_type(), blob);
/* modify entry in peercnts table as _not_ registered */
peercnt_modify(0, 0, &peer->addr);
/* Reset the address */
@@ -8701,6 +8709,8 @@ static int update_registry(struct sockaddr_in *sin, int callno, char *devtype, i
}
if (ast_sockaddr_cmp(&p->addr, &sockaddr)) {
+ RAII_VAR(struct ast_json *, blob, NULL, ast_json_unref);
+
if (iax2_regfunk) {
iax2_regfunk(p->name, 1);
}
@@ -8716,17 +8726,26 @@ static int update_registry(struct sockaddr_in *sin, int callno, char *devtype, i
ast_db_put("IAX/Registry", p->name, data);
ast_verb(3, "Registered IAX2 '%s' (%s) at %s:%d\n", p->name,
ast_test_flag(&iaxs[callno]->state, IAX_STATE_AUTHENTICATED) ? "AUTHENTICATED" : "UNAUTHENTICATED", ast_inet_ntoa(sin->sin_addr), ntohs(sin->sin_port));
- manager_event(EVENT_FLAG_SYSTEM, "PeerStatus", "ChannelType: IAX2\r\nPeer: IAX2/%s\r\nPeerStatus: Registered\r\nAddress: %s\r\nPort: %d\r\n", p->name, ast_inet_ntoa(sin->sin_addr), ntohs(sin->sin_port));
+ ast_endpoint_set_state(p->endpoint, AST_ENDPOINT_ONLINE);
+ blob = ast_json_pack("{s: s, s: s, s: i}",
+ "peer_status", "Registered",
+ "address", ast_inet_ntoa(sin->sin_addr),
+ "port", ntohs(sin->sin_port));
register_peer_exten(p, 1);
ast_devstate_changed(AST_DEVICE_UNKNOWN, AST_DEVSTATE_CACHABLE, "IAX2/%s", p->name); /* Activate notification */
} else if (!ast_test_flag64(p, IAX_TEMPONLY)) {
ast_verb(3, "Unregistered IAX2 '%s' (%s)\n", p->name,
ast_test_flag(&iaxs[callno]->state, IAX_STATE_AUTHENTICATED) ? "AUTHENTICATED" : "UNAUTHENTICATED");
- manager_event(EVENT_FLAG_SYSTEM, "PeerStatus", "ChannelType: IAX2\r\nPeer: IAX2/%s\r\nPeerStatus: Unregistered\r\n", p->name);
+ ast_endpoint_set_state(p->endpoint, AST_ENDPOINT_OFFLINE);
+ blob = ast_json_pack("{s: s}",
+ "peer_status", "Unregistered");
register_peer_exten(p, 0);
ast_db_del("IAX/Registry", p->name);
ast_devstate_changed(AST_DEVICE_UNAVAILABLE, AST_DEVSTATE_CACHABLE, "IAX2/%s", p->name); /* Activate notification */
}
+
+ ast_endpoint_blob_publish(p->endpoint, ast_endpoint_state_type(), blob);
+
/* Update the host */
/* Verify that the host is really there */
iax2_poke_peer(p, callno);
@@ -10759,20 +10778,28 @@ static int socket_process_helper(struct iax2_thread *thread)
log_jitterstats(fr->callno);
if (iaxs[fr->callno]->peerpoke) {
+ RAII_VAR(struct ast_json *, blob, NULL, ast_json_unref);
peer = iaxs[fr->callno]->peerpoke;
if ((peer->lastms < 0) || (peer->historicms > peer->maxms)) {
if (iaxs[fr->callno]->pingtime <= peer->maxms) {
ast_log(LOG_NOTICE, "Peer '%s' is now REACHABLE! Time: %d\n", peer->name, iaxs[fr->callno]->pingtime);
- manager_event(EVENT_FLAG_SYSTEM, "PeerStatus", "ChannelType: IAX2\r\nPeer: IAX2/%s\r\nPeerStatus: Reachable\r\nTime: %d\r\n", peer->name, iaxs[fr->callno]->pingtime);
+ ast_endpoint_set_state(peer->endpoint, AST_ENDPOINT_ONLINE);
+ blob = ast_json_pack("{s: s, s: i}",
+ "peer_status", "Reachable",
+ "time", iaxs[fr->callno]->pingtime);
ast_devstate_changed(AST_DEVICE_NOT_INUSE, AST_DEVSTATE_CACHABLE, "IAX2/%s", peer->name); /* Activate notification */
}
} else if ((peer->historicms > 0) && (peer->historicms <= peer->maxms)) {
if (iaxs[fr->callno]->pingtime > peer->maxms) {
ast_log(LOG_NOTICE, "Peer '%s' is now TOO LAGGED (%d ms)!\n", peer->name, iaxs[fr->callno]->pingtime);
- manager_event(EVENT_FLAG_SYSTEM, "PeerStatus", "ChannelType: IAX2\r\nPeer: IAX2/%s\r\nPeerStatus: Lagged\r\nTime: %d\r\n", peer->name, iaxs[fr->callno]->pingtime);
+ ast_endpoint_set_state(peer->endpoint, AST_ENDPOINT_ONLINE);
+ blob = ast_json_pack("{s: s, s: i}",
+ "peer_status", "Lagged",
+ "time", iaxs[fr->callno]->pingtime);
ast_devstate_changed(AST_DEVICE_UNAVAILABLE, AST_DEVSTATE_CACHABLE, "IAX2/%s", peer->name); /* Activate notification */
}
}
+ ast_endpoint_blob_publish(peer->endpoint, ast_endpoint_state_type(), blob);
peer->lastms = iaxs[fr->callno]->pingtime;
if (peer->smoothing && (peer->lastms > -1))
peer->historicms = (iaxs[fr->callno]->pingtime + peer->historicms) / 2;
@@ -11886,8 +11913,14 @@ static void __iax2_poke_noanswer(const void *data)
int callno;
if (peer->lastms > -1) {
+ RAII_VAR(struct ast_json *, blob, NULL, ast_json_unref);
+
ast_log(LOG_NOTICE, "Peer '%s' is now UNREACHABLE! Time: %d\n", peer->name, peer->lastms);
- manager_event(EVENT_FLAG_SYSTEM, "PeerStatus", "ChannelType: IAX2\r\nPeer: IAX2/%s\r\nPeerStatus: Unreachable\r\nTime: %d\r\n", peer->name, peer->lastms);
+ ast_endpoint_set_state(peer->endpoint, AST_ENDPOINT_OFFLINE);
+ blob = ast_json_pack("{s: s, s: i}",
+ "peer_status", "Unreachable",
+ "time", peer->lastms);
+ ast_endpoint_blob_publish(peer->endpoint, ast_endpoint_state_type(), blob);
ast_devstate_changed(AST_DEVICE_UNAVAILABLE, AST_DEVSTATE_CACHABLE, "IAX2/%s", peer->name); /* Activate notification */
}
if ((callno = peer->callno) > 0) {
@@ -12307,6 +12340,8 @@ static void peer_destructor(void *obj)
peer->mwi_event_sub = stasis_unsubscribe(peer->mwi_event_sub);
ast_string_field_free_memory(peer);
+
+ ast_endpoint_shutdown(peer->endpoint);
}
/*! \brief Create peer structure based on configuration */
@@ -12340,6 +12375,9 @@ static struct iax2_peer *build_peer(const char *name, struct ast_variable *v, st
peer->addr.len = sizeof(struct sockaddr_in);
if (ast_string_field_init(peer, 32))
peer = peer_unref(peer);
+ if (!(peer->endpoint = ast_endpoint_create("IAX2", name))) {
+ peer = peer_unref(peer);
+ }
}
if (peer) {
diff --git a/channels/chan_sip.c b/channels/chan_sip.c
index fbd7f1c22..c207e24fe 100644
--- a/channels/chan_sip.c
+++ b/channels/chan_sip.c
@@ -15724,6 +15724,7 @@ static void set_socket_transport(struct sip_socket *socket, int transport)
static int expire_register(const void *data)
{
struct sip_peer *peer = (struct sip_peer *)data;
+ RAII_VAR(struct ast_json *, blob, NULL, ast_json_unref);
if (!peer) { /* Hmmm. We have no peer. Weird. */
return 0;
@@ -15743,7 +15744,11 @@ static int expire_register(const void *data)
peer->socket.ws_session = NULL;
}
- manager_event(EVENT_FLAG_SYSTEM, "PeerStatus", "ChannelType: SIP\r\nPeer: SIP/%s\r\nPeerStatus: Unregistered\r\nCause: Expired\r\n", peer->name);
+ ast_endpoint_set_state(peer->endpoint, AST_ENDPOINT_OFFLINE);
+ blob = ast_json_pack("{s: s, s: s}",
+ "peer_status", "Unregistered",
+ "cause", "Expired");
+ ast_endpoint_blob_publish(peer->endpoint, ast_endpoint_state_type(), blob);
register_peer_exten(peer, FALSE); /* Remove regexten */
ast_devstate_changed(AST_DEVICE_UNKNOWN, AST_DEVSTATE_CACHABLE, "SIP/%s", peer->name);
@@ -15988,6 +15993,7 @@ static enum parse_register_result parse_register_contact(struct sip_pvt *pvt, st
int start = 0;
int wildcard_found = 0;
int single_binding_found = 0;
+ RAII_VAR(struct ast_json *, blob, NULL, ast_json_unref);
ast_copy_string(contact, __get_header(req, "Contact", &start), sizeof(contact));
@@ -16174,7 +16180,12 @@ static enum parse_register_result parse_register_contact(struct sip_pvt *pvt, st
}
ast_db_put("SIP/Registry", peer->name, data);
}
- manager_event(EVENT_FLAG_SYSTEM, "PeerStatus", "ChannelType: SIP\r\nPeer: SIP/%s\r\nPeerStatus: Registered\r\nAddress: %s\r\n", peer->name, ast_sockaddr_stringify(&peer->addr));
+
+ ast_endpoint_set_state(peer->endpoint, AST_ENDPOINT_ONLINE);
+ blob = ast_json_pack("{s: s, s: s}",
+ "peer_status", "Registered",
+ "address", ast_sockaddr_stringify(&peer->addr));
+ ast_endpoint_blob_publish(peer->endpoint, ast_endpoint_state_type(), blob);
/* Is this a new IP address for us? */
if (ast_sockaddr_cmp(&peer->addr, &oldsin)) {
@@ -17178,6 +17189,7 @@ static enum check_auth_result register_verify(struct sip_pvt *p, struct ast_sock
/* Create peer if we have autocreate mode enabled */
peer = temp_peer(name);
if (peer) {
+ RAII_VAR(struct ast_json *, blob, NULL, ast_json_unref);
ao2_t_link(peers, peer, "link peer into peer table");
if (!ast_sockaddr_isnull(&peer->addr)) {
ao2_t_link(peers_by_ip, peer, "link peer into peers-by-ip table");
@@ -17206,7 +17218,11 @@ static enum check_auth_result register_verify(struct sip_pvt *p, struct ast_sock
ast_string_field_set(p, fullcontact, peer->fullcontact);
/* Say OK and ask subsystem to retransmit msg counter */
transmit_response_with_date(p, "200 OK", req);
- manager_event(EVENT_FLAG_SYSTEM, "PeerStatus", "ChannelType: SIP\r\nPeer: SIP/%s\r\nPeerStatus: Registered\r\nAddress: %s\r\n", peer->name, ast_sockaddr_stringify(addr));
+ ast_endpoint_set_state(peer->endpoint, AST_ENDPOINT_ONLINE);
+ blob = ast_json_pack("{s: s, s: s}",
+ "peer_status", "Registered",
+ "address", ast_sockaddr_stringify(addr));
+ ast_endpoint_blob_publish(peer->endpoint, ast_endpoint_state_type(), blob);
send_mwi = 1;
res = 0;
break;
@@ -17225,6 +17241,8 @@ static enum check_auth_result register_verify(struct sip_pvt *p, struct ast_sock
ast_devstate_changed(AST_DEVICE_UNKNOWN, AST_DEVSTATE_CACHABLE, "SIP/%s", peer->name);
}
if (res < 0) {
+ RAII_VAR(struct ast_json *, blob, NULL, ast_json_unref);
+
switch (res) {
case AUTH_SECRET_FAILED:
/* Wrong password in authentication. Go away, don't try again until you fixed it */
@@ -17232,14 +17250,12 @@ static enum check_auth_result register_verify(struct sip_pvt *p, struct ast_sock
if (global_authfailureevents) {
const char *peer_addr = ast_strdupa(ast_sockaddr_stringify_addr(addr));
const char *peer_port = ast_strdupa(ast_sockaddr_stringify_port(addr));
- manager_event(EVENT_FLAG_SYSTEM, "PeerStatus",
- "ChannelType: SIP\r\n"
- "Peer: SIP/%s\r\n"
- "PeerStatus: Rejected\r\n"
- "Cause: AUTH_SECRET_FAILED\r\n"
- "Address: %s\r\n"
- "Port: %s\r\n",
- name, peer_addr, peer_port);
+
+ blob = ast_json_pack("{s: s, s: s, s: s, s: s}",
+ "peer_status", "Rejected",
+ "cause", "AUTH_SECRET_FAILED",
+ "address", peer_addr,
+ "port", peer_port);
}
break;
case AUTH_USERNAME_MISMATCH:
@@ -17255,16 +17271,12 @@ static enum check_auth_result register_verify(struct sip_pvt *p, struct ast_sock
if (global_authfailureevents) {
const char *peer_addr = ast_strdupa(ast_sockaddr_stringify_addr(addr));
const char *peer_port = ast_strdupa(ast_sockaddr_stringify_port(addr));
- manager_event(EVENT_FLAG_SYSTEM, "PeerStatus",
- "ChannelType: SIP\r\n"
- "Peer: SIP/%s\r\n"
- "PeerStatus: Rejected\r\n"
- "Cause: %s\r\n"
- "Address: %s\r\n"
- "Port: %s\r\n",
- name,
- res == AUTH_PEER_NOT_DYNAMIC ? "AUTH_PEER_NOT_DYNAMIC" : "URI_NOT_FOUND",
- peer_addr, peer_port);
+
+ blob = ast_json_pack("{s: s, s: s, s: s, s: s}",
+ "peer_status", "Rejected",
+ "cause", res == AUTH_PEER_NOT_DYNAMIC ? "AUTH_PEER_NOT_DYNAMIC" : "URI_NOT_FOUND",
+ "address", peer_addr,
+ "port", peer_port);
}
} else {
/* URI not found */
@@ -17273,30 +17285,24 @@ static enum check_auth_result register_verify(struct sip_pvt *p, struct ast_sock
if (global_authfailureevents) {
const char *peer_addr = ast_strdupa(ast_sockaddr_stringify_addr(addr));
const char *peer_port = ast_strdupa(ast_sockaddr_stringify_port(addr));
- manager_event(EVENT_FLAG_SYSTEM, "PeerStatus",
- "ChannelType: SIP\r\n"
- "Peer: SIP/%s\r\n"
- "PeerStatus: Rejected\r\n"
- "Cause: AUTH_PEER_NOT_DYNAMIC\r\n"
- "Address: %s\r\n"
- "Port: %s\r\n",
- name, peer_addr, peer_port);
+
+ blob = ast_json_pack("{s: s, s: s, s: s, s: s}",
+ "peer_status", "Rejected",
+ "cause", "AUTH_PEER_NOT_DYNAMIC",
+ "address", peer_addr,
+ "port", peer_port);
}
} else {
transmit_response(p, "404 Not found", &p->initreq);
if (global_authfailureevents) {
const char *peer_addr = ast_strdupa(ast_sockaddr_stringify_addr(addr));
const char *peer_port = ast_strdupa(ast_sockaddr_stringify_port(addr));
- manager_event(EVENT_FLAG_SYSTEM, "PeerStatus",
- "ChannelType: SIP\r\n"
- "Peer: SIP/%s\r\n"
- "PeerStatus: Rejected\r\n"
- "Cause: %s\r\n"
- "Address: %s\r\n"
- "Port: %s\r\n",
- name,
- (res == AUTH_USERNAME_MISMATCH) ? "AUTH_USERNAME_MISMATCH" : "URI_NOT_FOUND",
- peer_addr, peer_port);
+
+ blob = ast_json_pack("{s: s, s: s, s: s, s: s}",
+ "peer_status", "Rejected",
+ "cause", (res == AUTH_USERNAME_MISMATCH) ? "AUTH_USERNAME_MISMATCH" : "URI_NOT_FOUND",
+ "address", peer_addr,
+ "port", peer_port);
}
}
}
@@ -17305,6 +17311,8 @@ static enum check_auth_result register_verify(struct sip_pvt *p, struct ast_sock
default:
break;
}
+
+ ast_endpoint_blob_publish(peer->endpoint, ast_endpoint_state_type(), blob);
}
if (peer) {
sip_unref_peer(peer, "register_verify: sip_unref_peer: tossing stack peer pointer at end of func");
@@ -23804,6 +23812,8 @@ static void handle_response_peerpoke(struct sip_pvt *p, int resp, struct sip_req
if (statechanged) {
const char *s = is_reachable ? "Reachable" : "Lagged";
char str_lastms[20];
+ RAII_VAR(struct ast_json *, blob, NULL, ast_json_unref);
+
snprintf(str_lastms, sizeof(str_lastms), "%d", pingtime);
ast_log(LOG_NOTICE, "Peer '%s' is now %s. (%dms / %dms)\n",
@@ -23812,9 +23822,11 @@ static void handle_response_peerpoke(struct sip_pvt *p, int resp, struct sip_req
if (sip_cfg.peer_rtupdate) {
ast_update_realtime(ast_check_realtime("sipregs") ? "sipregs" : "sippeers", "name", peer->name, "lastms", str_lastms, SENTINEL);
}
- manager_event(EVENT_FLAG_SYSTEM, "PeerStatus",
- "ChannelType: SIP\r\nPeer: SIP/%s\r\nPeerStatus: %s\r\nTime: %d\r\n",
- peer->name, s, pingtime);
+ ast_endpoint_set_state(peer->endpoint, AST_ENDPOINT_ONLINE);
+ blob = ast_json_pack("{s: s, s: i}",
+ "peer_status", s,
+ "time", pingtime);
+ ast_endpoint_blob_publish(peer->endpoint, ast_endpoint_state_type(), blob);
if (is_reachable && sip_cfg.regextenonqualify)
register_peer_exten(peer, TRUE);
}
@@ -29094,11 +29106,17 @@ static int sip_poke_noanswer(const void *data)
peer->pokeexpire = -1;
if (peer->lastms > -1) {
+ RAII_VAR(struct ast_json *, blob, NULL, ast_json_unref);
+
ast_log(LOG_NOTICE, "Peer '%s' is now UNREACHABLE! Last qualify: %d\n", peer->name, peer->lastms);
if (sip_cfg.peer_rtupdate) {
ast_update_realtime(ast_check_realtime("sipregs") ? "sipregs" : "sippeers", "name", peer->name, "lastms", "-1", SENTINEL);
}
- manager_event(EVENT_FLAG_SYSTEM, "PeerStatus", "ChannelType: SIP\r\nPeer: SIP/%s\r\nPeerStatus: Unreachable\r\nTime: %d\r\n", peer->name, -1);
+ ast_endpoint_set_state(peer->endpoint, AST_ENDPOINT_OFFLINE);
+ blob = ast_json_pack("{s: s, s: s}",
+ "peer_status", "Unreachable",
+ "time", "-1");
+ ast_endpoint_blob_publish(peer->endpoint, ast_endpoint_state_type(), blob);
if (sip_cfg.regextenonqualify) {
register_peer_exten(peer, FALSE);
}
diff --git a/channels/chan_skinny.c b/channels/chan_skinny.c
index ad51edf10..9bdc0f2d3 100644
--- a/channels/chan_skinny.c
+++ b/channels/chan_skinny.c
@@ -80,6 +80,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/event.h"
#include "asterisk/indications.h"
#include "asterisk/linkedlists.h"
+#include "asterisk/stasis_endpoints.h"
#include "asterisk/bridging.h"
/*** DOCUMENTATION
@@ -1585,6 +1586,7 @@ struct skinny_device {
struct skinny_line *activeline;
struct ast_format_cap *cap;
struct ast_format_cap *confcap;
+ struct ast_endpoint *endpoint;
AST_LIST_HEAD(, skinny_line) lines;
AST_LIST_HEAD(, skinny_speeddial) speeddials;
AST_LIST_HEAD(, skinny_serviceurl) serviceurls;
@@ -1687,7 +1689,7 @@ static struct skinny_line *skinny_line_destroy(struct skinny_line *l)
ast_free(l);
return NULL;
}
-static struct skinny_device *skinny_device_alloc(void)
+static struct skinny_device *skinny_device_alloc(const char *dname)
{
struct skinny_device *d;
if (!(d = ast_calloc(1, sizeof(*d)))) {
@@ -1696,18 +1698,23 @@ static struct skinny_device *skinny_device_alloc(void)
d->cap = ast_format_cap_alloc_nolock();
d->confcap = ast_format_cap_alloc_nolock();
- if (!d->cap || !d->confcap) {
+ d->endpoint = ast_endpoint_create("Skinny", dname);
+ if (!d->cap || !d->confcap || !d->endpoint) {
d->cap = ast_format_cap_destroy(d->cap);
d->confcap = ast_format_cap_destroy(d->confcap);
ast_free(d);
return NULL;
}
+
+ ast_copy_string(d->name, dname, sizeof(d->name));
+
return d;
}
static struct skinny_device *skinny_device_destroy(struct skinny_device *d)
{
d->cap = ast_format_cap_destroy(d->cap);
d->confcap = ast_format_cap_destroy(d->confcap);
+ ast_endpoint_shutdown(d->endpoint);
ast_free(d);
return NULL;
}
@@ -2244,6 +2251,8 @@ static int skinny_register(struct skinny_req *req, struct skinnysession *s)
ast_sockaddr_from_sin(&addr, &s->sin);
if (!d->session && !strcasecmp(req->data.reg.name, d->id)
&& ast_apply_ha(d->ha, &addr)) {
+ RAII_VAR(struct ast_json *, blob, NULL, ast_json_unref);
+
s->device = d;
d->type = letohl(req->data.reg.type);
d->protocolversion = letohl(req->data.reg.protocolVersion);
@@ -2277,7 +2286,6 @@ static int skinny_register(struct skinny_req *req, struct skinnysession *s)
l->instance = instance;
l->newmsgs = ast_app_has_voicemail(l->mailbox, NULL);
set_callforwards(l, NULL, SKINNY_CFWD_ALL|SKINNY_CFWD_BUSY|SKINNY_CFWD_NOANSWER);
- manager_event(EVENT_FLAG_SYSTEM, "PeerStatus", "ChannelType: Skinny\r\nPeer: Skinny/%s@%s\r\nPeerStatus: Registered\r\n", l->name, d->name);
register_exten(l);
/* initialize MWI on line and device */
mwi_event_cb(l, NULL, NULL, NULL);
@@ -2287,6 +2295,9 @@ static int skinny_register(struct skinny_req *req, struct skinnysession *s)
ast_devstate_changed(AST_DEVICE_NOT_INUSE, AST_DEVSTATE_CACHABLE, "Skinny/%s", l->name);
--instance;
}
+ ast_endpoint_set_state(d->endpoint, AST_ENDPOINT_ONLINE);
+ blob = ast_json_pack("{s: s}", "peer_status", "Registered");
+ ast_endpoint_blob_publish(d->endpoint, ast_endpoint_state_type(), blob);
break;
}
}
@@ -2306,6 +2317,7 @@ static int skinny_unregister(struct skinny_req *req, struct skinnysession *s)
d = s->device;
if (d) {
+ RAII_VAR(struct ast_json *, blob, NULL, ast_json_unref);
d->session = NULL;
AST_LIST_TRAVERSE(&d->speeddials, sd, list) {
@@ -2317,11 +2329,14 @@ static int skinny_unregister(struct skinny_req *req, struct skinnysession *s)
ast_format_cap_remove_all(l->cap);
ast_parse_allow_disallow(&l->prefs, l->cap, "all", 0);
l->instance = 0;
- manager_event(EVENT_FLAG_SYSTEM, "PeerStatus", "ChannelType: Skinny\r\nPeer: Skinny/%s@%s\r\nPeerStatus: Unregistered\r\n", l->name, d->name);
unregister_exten(l);
ast_devstate_changed(AST_DEVICE_UNAVAILABLE, AST_DEVSTATE_CACHABLE, "Skinny/%s", l->name);
}
}
+
+ ast_endpoint_set_state(d->endpoint, AST_ENDPOINT_OFFLINE);
+ blob = ast_json_pack("{s: s}", "peer_status", "Unregistered");
+ ast_endpoint_blob_publish(d->endpoint, ast_endpoint_state_type(), blob);
}
return -1; /* main loop will destroy the session */
@@ -8220,7 +8235,7 @@ static struct skinny_device *config_device(const char *dname, struct ast_variabl
}
}
- if (!(d = skinny_device_alloc())) {
+ if (!(d = skinny_device_alloc(dname))) {
ast_verb(1, "Unable to allocate memory for device %s.\n", dname);
AST_LIST_UNLOCK(&devices);
return NULL;
@@ -8613,6 +8628,8 @@ static int unload_module(void)
AST_LIST_LOCK(&sessions);
/* Destroy all the interfaces and free their memory */
while((s = AST_LIST_REMOVE_HEAD(&sessions, list))) {
+ RAII_VAR(struct ast_json *, blob, NULL, ast_json_unref);
+
d = s->device;
AST_LIST_TRAVERSE(&d->lines, l, list){
ast_mutex_lock(&l->lock);
@@ -8627,9 +8644,11 @@ static int unload_module(void)
l->mwi_event_sub = stasis_unsubscribe(l->mwi_event_sub);
}
ast_mutex_unlock(&l->lock);
- manager_event(EVENT_FLAG_SYSTEM, "PeerStatus", "ChannelType: Skinny\r\nPeer: Skinny/%s@%s\r\nPeerStatus: Unregistered\r\n", l->name, d->name);
unregister_exten(l);
}
+ ast_endpoint_set_state(d->endpoint, AST_ENDPOINT_OFFLINE);
+ blob = ast_json_pack("{s: s}", "peer_status", "Unregistered");
+ ast_endpoint_blob_publish(d->endpoint, ast_endpoint_state_type(), blob);
if (s->fd > -1)
close(s->fd);
pthread_cancel(s->t);