diff --git a/apps/app_confbridge.c b/apps/app_confbridge.c index 18cfb746c7..a4eea43b8f 100644 --- a/apps/app_confbridge.c +++ b/apps/app_confbridge.c @@ -486,7 +486,7 @@ static struct conference_bridge *join_conference_bridge(const char *name, struct /* Set the device state for this conference */ if (conference_bridge->users == 1) { - ast_devstate_changed(AST_DEVICE_INUSE, "confbridge:%s", conference_bridge->name); + ast_devstate_changed(AST_DEVICE_INUSE, AST_DEVSTATE_CACHABLE, "confbridge:%s", conference_bridge->name); } /* If the caller is a marked user or is waiting for a marked user to enter pass 'em off, otherwise pass them off to do regular joining stuff */ @@ -568,7 +568,7 @@ static void leave_conference_bridge(struct conference_bridge *conference_bridge } } else { /* Set device state to "not in use" */ - ast_devstate_changed(AST_DEVICE_NOT_INUSE, "confbridge:%s", conference_bridge->name); + ast_devstate_changed(AST_DEVICE_NOT_INUSE, AST_DEVSTATE_CACHABLE, "confbridge:%s", conference_bridge->name); ao2_unlink(conference_bridges, conference_bridge); } diff --git a/apps/app_meetme.c b/apps/app_meetme.c index 64e788359b..1f2286e09c 100644 --- a/apps/app_meetme.c +++ b/apps/app_meetme.c @@ -2576,7 +2576,7 @@ static int conf_run(struct ast_channel *chan, struct ast_conference *conf, struc /* This device changed state now - if this is the first user */ if (conf->users == 1) - ast_devstate_changed(AST_DEVICE_INUSE, "meetme:%s", conf->confno); + ast_devstate_changed(AST_DEVICE_INUSE, (conf->isdynamic ? AST_DEVSTATE_NOT_CACHABLE : AST_DEVSTATE_CACHABLE), "meetme:%s", conf->confno); ast_mutex_unlock(&conf->playlock); @@ -3884,7 +3884,7 @@ bailoutandtrynormal: /* Change any states */ if (!conf->users) { - ast_devstate_changed(AST_DEVICE_NOT_INUSE, "meetme:%s", conf->confno); + ast_devstate_changed(AST_DEVICE_NOT_INUSE, (conf->isdynamic ? AST_DEVSTATE_NOT_CACHABLE : AST_DEVSTATE_CACHABLE), "meetme:%s", conf->confno); } /* Return the number of seconds the user was in the conf */ @@ -5303,8 +5303,8 @@ static void sla_change_trunk_state(const struct sla_trunk *trunk, enum sla_trunk || trunk_ref == exclude) continue; trunk_ref->state = state; - ast_devstate_changed(sla_state_to_devstate(state), - "SLA:%s_%s", station->name, trunk->name); + ast_devstate_changed(sla_state_to_devstate(state), AST_DEVSTATE_CACHABLE, + "SLA:%s_%s", station->name, trunk->name); break; } } @@ -5802,8 +5802,8 @@ static void sla_handle_hold_event(struct sla_event *event) { ast_atomic_fetchadd_int((int *) &event->trunk_ref->trunk->hold_stations, 1); event->trunk_ref->state = SLA_TRUNK_STATE_ONHOLD_BYME; - ast_devstate_changed(AST_DEVICE_ONHOLD, "SLA:%s_%s", - event->station->name, event->trunk_ref->trunk->name); + ast_devstate_changed(AST_DEVICE_ONHOLD, AST_DEVSTATE_CACHABLE, "SLA:%s_%s", + event->station->name, event->trunk_ref->trunk->name); sla_change_trunk_state(event->trunk_ref->trunk, SLA_TRUNK_STATE_ONHOLD, INACTIVE_TRUNK_REFS, event->trunk_ref); @@ -6312,8 +6312,8 @@ static int sla_station_exec(struct ast_channel *chan, const char *data) sla_change_trunk_state(trunk_ref->trunk, SLA_TRUNK_STATE_UP, ALL_TRUNK_REFS, NULL); else { trunk_ref->state = SLA_TRUNK_STATE_UP; - ast_devstate_changed(AST_DEVICE_INUSE, - "SLA:%s_%s", station->name, trunk_ref->trunk->name); + ast_devstate_changed(AST_DEVICE_INUSE, AST_DEVSTATE_CACHABLE, + "SLA:%s_%s", station->name, trunk_ref->trunk->name); } } else if (trunk_ref->state == SLA_TRUNK_STATE_RINGING) { struct sla_ringing_trunk *ringing_trunk; diff --git a/channels/chan_agent.c b/channels/chan_agent.c index 06c64b26fa..92aa796817 100644 --- a/channels/chan_agent.c +++ b/channels/chan_agent.c @@ -618,7 +618,7 @@ static struct ast_frame *agent_read(struct ast_channel *ast) if (p->chan) { p->chan->_bridge = NULL; p->chan = NULL; - ast_devstate_changed(AST_DEVICE_UNAVAILABLE, "Agent/%s", p->agent); + ast_devstate_changed(AST_DEVICE_UNAVAILABLE, AST_DEVSTATE_CACHABLE, "Agent/%s", p->agent); p->acknowledged = 0; } } else { @@ -875,7 +875,7 @@ static int agent_call(struct ast_channel *ast, char *dest, int timeout) } else { /* Agent hung-up */ p->chan = NULL; - ast_devstate_changed(AST_DEVICE_UNAVAILABLE, "Agent/%s", p->agent); + ast_devstate_changed(AST_DEVICE_UNAVAILABLE, AST_DEVSTATE_CACHABLE, "Agent/%s", p->agent); } if (!res) { @@ -994,7 +994,7 @@ static int agent_hangup(struct ast_channel *ast) if (!p->loginstart) { p->logincallerid[0] = '\0'; } else { - ast_devstate_changed(AST_DEVICE_NOT_INUSE, "Agent/%s", p->agent); + ast_devstate_changed(AST_DEVICE_NOT_INUSE, AST_DEVSTATE_CACHABLE, "Agent/%s", p->agent); } if (p->abouttograb) { @@ -2138,7 +2138,7 @@ static int login_exec(struct ast_channel *chan, const char *data) } ast_mutex_unlock(&p->lock); AST_LIST_UNLOCK(&agents); - ast_devstate_changed(AST_DEVICE_NOT_INUSE, "Agent/%s", p->agent); + ast_devstate_changed(AST_DEVICE_NOT_INUSE, AST_DEVSTATE_CACHABLE, "Agent/%s", p->agent); while (res >= 0) { ast_mutex_lock(&p->lock); if (p->deferlogoff && p->chan) { @@ -2159,7 +2159,7 @@ static int login_exec(struct ast_channel *chan, const char *data) if (ast_tvdiff_ms(ast_tvnow(), p->lastdisc) > 0) { ast_debug(1, "Wrapup time for %s expired!\n", p->agent); p->lastdisc = ast_tv(0, 0); - ast_devstate_changed(AST_DEVICE_NOT_INUSE, "Agent/%s", p->agent); + ast_devstate_changed(AST_DEVICE_NOT_INUSE, AST_DEVSTATE_CACHABLE, "Agent/%s", p->agent); if (p->ackcall) { check_beep(p, 0); } else { @@ -2219,7 +2219,7 @@ static int login_exec(struct ast_channel *chan, const char *data) ast_queue_log("NONE", chan->uniqueid, agent, "AGENTLOGOFF", "%s|%ld", chan->name, logintime); ast_verb(2, "Agent '%s' logged out\n", p->agent); /* If there is no owner, go ahead and kill it now */ - ast_devstate_changed(AST_DEVICE_UNAVAILABLE, "Agent/%s", p->agent); + ast_devstate_changed(AST_DEVICE_UNAVAILABLE, AST_DEVSTATE_CACHABLE, "Agent/%s", p->agent); if (p->dead && !p->owner) { ast_mutex_destroy(&p->lock); ast_cond_destroy(&p->app_complete_cond); diff --git a/channels/chan_dahdi.c b/channels/chan_dahdi.c index ccd8f3b1d2..a95a8ce3ac 100644 --- a/channels/chan_dahdi.c +++ b/channels/chan_dahdi.c @@ -3364,7 +3364,7 @@ static void dahdi_pri_update_span_devstate(struct sig_pri_span *pri) } if (pri->congestion_devstate != new_state) { pri->congestion_devstate = new_state; - ast_devstate_changed(AST_DEVICE_UNKNOWN, "DAHDI/I%d/congestion", pri->span); + ast_devstate_changed(AST_DEVICE_UNKNOWN, AST_DEVSTATE_NOT_CACHABLE, "DAHDI/I%d/congestion", pri->span); } #if defined(THRESHOLD_DEVSTATE_PLACEHOLDER) /* Update the span threshold device state and report any change. */ @@ -3380,7 +3380,7 @@ static void dahdi_pri_update_span_devstate(struct sig_pri_span *pri) } if (pri->threshold_devstate != new_state) { pri->threshold_devstate = new_state; - ast_devstate_changed(AST_DEVICE_UNKNOWN, "DAHDI/I%d/threshold", pri->span); + ast_devstate_changed(AST_DEVICE_UNKNOWN, AST_DEVSTATE_NOT_CACHABLE, "DAHDI/I%d/threshold", pri->span); } #endif /* defined(THRESHOLD_DEVSTATE_PLACEHOLDER) */ } @@ -9804,7 +9804,8 @@ static struct ast_channel *dahdi_new(struct dahdi_pvt *i, int state, int startpb if (dashptr) { *dashptr = '\0'; } - ast_devstate_changed_literal(AST_DEVICE_UNKNOWN, device_name); + tmp->flags |= AST_FLAG_DISABLE_DEVSTATE_CACHE; + ast_devstate_changed_literal(AST_DEVICE_UNKNOWN, AST_DEVSTATE_NOT_CACHABLE, device_name); for (v = i->vars ; v ; v = v->next) pbx_builtin_setvar_helper(tmp, v->name, v->value); diff --git a/channels/chan_iax2.c b/channels/chan_iax2.c index d7eeb245a3..7a17c26ed6 100644 --- a/channels/chan_iax2.c +++ b/channels/chan_iax2.c @@ -5729,7 +5729,7 @@ static int iax2_getpeertrunk(struct sockaddr_in sin) } /*! \brief Create new call, interface with the PBX core */ -static struct ast_channel *ast_iax2_new(int callno, int state, format_t capability, const char *linkedid) +static struct ast_channel *ast_iax2_new(int callno, int state, format_t capability, const char *linkedid, unsigned int cachable) { struct ast_channel *tmp; struct chan_iax2_pvt *i; @@ -5798,6 +5798,10 @@ static struct ast_channel *ast_iax2_new(int callno, int state, format_t capabili i->owner = tmp; i->capability = capability; + if (!cachable) { + tmp->flags |= AST_FLAG_DISABLE_DEVSTATE_CACHE; + } + /* Set inherited variables */ if (i->vars) { for (v = i->vars ; v ; v = v->next) @@ -8084,7 +8088,7 @@ static int register_verify(int callno, struct sockaddr_in *sin, struct iax_ies * /* if challenge has been sent, but no challenge response if given, reject. */ goto return_unref; } - ast_devstate_changed(AST_DEVICE_UNKNOWN, "IAX2/%s", p->name); /* Activate notification */ + ast_devstate_changed(AST_DEVICE_UNKNOWN, AST_DEVSTATE_CACHABLE, "IAX2/%s", p->name); /* Activate notification */ /* either Authentication has taken place, or a REGAUTH must be sent before verifying registration */ res = 0; @@ -8638,7 +8642,7 @@ static void __expire_registry(const void *data) if (!ast_test_flag64(peer, IAX_TEMPONLY)) ast_db_del("IAX/Registry", peer->name); register_peer_exten(peer, 0); - ast_devstate_changed(AST_DEVICE_UNAVAILABLE, "IAX2/%s", peer->name); /* Activate notification */ + ast_devstate_changed(AST_DEVICE_UNAVAILABLE, AST_DEVSTATE_CACHABLE, "IAX2/%s", peer->name); /* Activate notification */ if (iax2_regfunk) iax2_regfunk(peer->name, 0); @@ -8693,7 +8697,7 @@ static void reg_source_db(struct iax2_peer *p) } } - ast_devstate_changed(AST_DEVICE_UNKNOWN, "IAX2/%s", p->name); /* Activate notification */ + ast_devstate_changed(AST_DEVICE_UNKNOWN, AST_DEVSTATE_CACHABLE, "IAX2/%s", p->name); /* Activate notification */ p->expire = iax2_sched_add(sched, (p->expiry + 10) * 1000, expire_registry, peer_ref(p)); if (p->expire == -1) { @@ -8770,14 +8774,14 @@ static int update_registry(struct sockaddr_in *sin, int callno, char *devtype, i 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\n", p->name); register_peer_exten(p, 1); - ast_devstate_changed(AST_DEVICE_UNKNOWN, "IAX2/%s", p->name); /* Activate notification */ + 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); register_peer_exten(p, 0); ast_db_del("IAX/Registry", p->name); - ast_devstate_changed(AST_DEVICE_UNAVAILABLE, "IAX2/%s", p->name); /* Activate notification */ + ast_devstate_changed(AST_DEVICE_UNAVAILABLE, AST_DEVSTATE_CACHABLE, "IAX2/%s", p->name); /* Activate notification */ } /* Update the host */ /* Verify that the host is really there */ @@ -10291,7 +10295,8 @@ static int socket_process(struct iax2_thread *thread) (f.frametype == AST_FRAME_IAX)) { if (ast_test_flag64(iaxs[fr->callno], IAX_DELAYPBXSTART)) { ast_clear_flag64(iaxs[fr->callno], IAX_DELAYPBXSTART); - if (!ast_iax2_new(fr->callno, AST_STATE_RING, iaxs[fr->callno]->chosenformat, NULL)) { + if (!ast_iax2_new(fr->callno, AST_STATE_RING, iaxs[fr->callno]->chosenformat, NULL, + ast_test_flag(&iaxs[fr->callno]->state, IAX_STATE_AUTHENTICATED))) { ast_variables_destroy(ies.vars); ast_mutex_unlock(&iaxsl[fr->callno]); return 1; @@ -10924,13 +10929,13 @@ static int socket_process(struct iax2_thread *thread) 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_devstate_changed(AST_DEVICE_NOT_INUSE, "IAX2/%s", peer->name); /* Activate notification */ + 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_devstate_changed(AST_DEVICE_UNAVAILABLE, "IAX2/%s", peer->name); /* Activate notification */ + ast_devstate_changed(AST_DEVICE_UNAVAILABLE, AST_DEVSTATE_CACHABLE, "IAX2/%s", peer->name); /* Activate notification */ } } peer->lastms = iaxs[fr->callno]->pingtime; @@ -11172,7 +11177,7 @@ static int socket_process(struct iax2_thread *thread) using_prefs); ast_set_flag(&iaxs[fr->callno]->state, IAX_STATE_STARTED); - if (!(c = ast_iax2_new(fr->callno, AST_STATE_RING, format, NULL))) + if (!(c = ast_iax2_new(fr->callno, AST_STATE_RING, format, NULL, 1))) iax2_destroy(fr->callno); else if (ies.vars) { struct ast_datastore *variablestore; @@ -11243,7 +11248,7 @@ immediatedial: ast_getformatname_multiple(tmp, sizeof(tmp), iaxs[fr->callno]->peerformat)); ast_set_flag(&iaxs[fr->callno]->state, IAX_STATE_STARTED); send_command(iaxs[fr->callno], AST_FRAME_CONTROL, AST_CONTROL_PROGRESS, 0, NULL, 0, -1); - if (!(c = ast_iax2_new(fr->callno, AST_STATE_RING, iaxs[fr->callno]->peerformat, NULL))) + if (!(c = ast_iax2_new(fr->callno, AST_STATE_RING, iaxs[fr->callno]->peerformat, NULL, 1))) iax2_destroy(fr->callno); else if (ies.vars) { struct ast_datastore *variablestore; @@ -11996,7 +12001,7 @@ static void __iax2_poke_noanswer(const void *data) if (peer->lastms > -1) { 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_devstate_changed(AST_DEVICE_UNAVAILABLE, "IAX2/%s", peer->name); /* Activate notification */ + ast_devstate_changed(AST_DEVICE_UNAVAILABLE, AST_DEVSTATE_CACHABLE, "IAX2/%s", peer->name); /* Activate notification */ } if ((callno = peer->callno) > 0) { ast_mutex_lock(&iaxsl[callno]); @@ -12164,7 +12169,7 @@ static struct ast_channel *iax2_request(const char *type, format_t format, const if (cai.found) ast_string_field_set(iaxs[callno], host, pds.peer); - c = ast_iax2_new(callno, AST_STATE_DOWN, cai.capability, requestor ? requestor->linkedid : NULL); + c = ast_iax2_new(callno, AST_STATE_DOWN, cai.capability, requestor ? requestor->linkedid : NULL, cai.found); ast_mutex_unlock(&iaxsl[callno]); diff --git a/channels/chan_local.c b/channels/chan_local.c index 459bd5b12d..2d283eb719 100644 --- a/channels/chan_local.c +++ b/channels/chan_local.c @@ -1229,6 +1229,9 @@ static struct ast_channel *local_new(struct local_pvt *p, int state, const char tmp->tech_pvt = p; tmp2->tech_pvt = p; + tmp->flags |= AST_FLAG_DISABLE_DEVSTATE_CACHE; + tmp2->flags |= AST_FLAG_DISABLE_DEVSTATE_CACHE; + p->owner = tmp; p->chan = tmp2; diff --git a/channels/chan_sip.c b/channels/chan_sip.c index 7e51ed5139..4687f87b99 100644 --- a/channels/chan_sip.c +++ b/channels/chan_sip.c @@ -6418,7 +6418,7 @@ static int update_call_counter(struct sip_pvt *fup, int event) } if (p) { - ast_devstate_changed(AST_DEVICE_UNKNOWN, "SIP/%s", p->name); + ast_devstate_changed(AST_DEVICE_UNKNOWN, AST_DEVSTATE_CACHABLE, "SIP/%s", p->name); unref_peer(p, "update_call_counter: unref_peer from call counter"); } return 0; @@ -7609,6 +7609,9 @@ static struct ast_channel *sip_new(struct sip_pvt *i, int state, const char *tit if (i->rtp) ast_jb_configure(tmp, &global_jbconf); + if (!i->relatedpeer) { + tmp->flags |= AST_FLAG_DISABLE_DEVSTATE_CACHE; + } /* Set channel variables for this call from configuration */ for (v = i->chanvars ; v ; v = v->next) { char valuebuf[1024]; @@ -14221,7 +14224,7 @@ static int expire_register(const void *data) manager_event(EVENT_FLAG_SYSTEM, "PeerStatus", "ChannelType: SIP\r\nPeer: SIP/%s\r\nPeerStatus: Unregistered\r\nCause: Expired\r\n", peer->name); register_peer_exten(peer, FALSE); /* Remove regexten */ - ast_devstate_changed(AST_DEVICE_UNKNOWN, "SIP/%s", peer->name); + ast_devstate_changed(AST_DEVICE_UNKNOWN, AST_DEVSTATE_CACHABLE, "SIP/%s", peer->name); /* Do we need to release this peer from memory? Only for realtime peers and autocreated peers @@ -15003,8 +15006,9 @@ static void sip_peer_hold(struct sip_pvt *p, int hold) ast_atomic_fetchadd_int(&p->relatedpeer->onHold, (hold ? +1 : -1)); /* Request device state update */ - ast_devstate_changed(AST_DEVICE_UNKNOWN, "SIP/%s", p->relatedpeer->name); - + ast_devstate_changed(AST_DEVICE_UNKNOWN, (p->owner->flags & AST_FLAG_DISABLE_DEVSTATE_CACHE ? AST_DEVSTATE_NOT_CACHABLE : AST_DEVSTATE_CACHABLE), + "SIP/%s", p->relatedpeer->name); + return; } @@ -15422,7 +15426,7 @@ static enum check_auth_result register_verify(struct sip_pvt *p, struct ast_sock } else { update_peer_lastmsgssent(peer, -1, 0); } - ast_devstate_changed(AST_DEVICE_UNKNOWN, "SIP/%s", peer->name); + ast_devstate_changed(AST_DEVICE_UNKNOWN, AST_DEVSTATE_CACHABLE, "SIP/%s", peer->name); } if (res < 0) { switch (res) { @@ -21414,7 +21418,7 @@ static void handle_response_peerpoke(struct sip_pvt *p, int resp, struct sip_req ast_log(LOG_NOTICE, "Peer '%s' is now %s. (%dms / %dms)\n", peer->name, s, pingtime, peer->maxms); - ast_devstate_changed(AST_DEVICE_UNKNOWN, "SIP/%s", peer->name); + ast_devstate_changed(AST_DEVICE_UNKNOWN, AST_DEVSTATE_CACHABLE, "SIP/%s", peer->name); if (sip_cfg.peer_rtupdate) { ast_update_realtime(ast_check_realtime("sipregs") ? "sipregs" : "sippeers", "name", peer->name, "lastms", str_lastms, SENTINEL); } @@ -26870,7 +26874,7 @@ static int sip_poke_noanswer(const void *data) /* Don't send a devstate change if nothing changed. */ if (peer->lastms > -1) { peer->lastms = -1; - ast_devstate_changed(AST_DEVICE_UNKNOWN, "SIP/%s", peer->name); + ast_devstate_changed(AST_DEVICE_UNKNOWN, AST_DEVSTATE_CACHABLE, "SIP/%s", peer->name); } /* Try again quickly */ diff --git a/channels/chan_skinny.c b/channels/chan_skinny.c index a92bd48bc8..0b16a34ede 100644 --- a/channels/chan_skinny.c +++ b/channels/chan_skinny.c @@ -1925,7 +1925,7 @@ static int skinny_register(struct skinny_req *req, struct skinnysession *s) register_exten(l); /* initialize MWI on line and device */ mwi_event_cb(0, l); - ast_devstate_changed(AST_DEVICE_NOT_INUSE, "Skinny/%s@%s", l->name, d->name); + ast_devstate_changed(AST_DEVICE_NOT_INUSE, AST_DEVSTATE_CACHABLE, "Skinny/%s@%s", l->name, d->name); } --instance; } @@ -1963,7 +1963,7 @@ static int skinny_unregister(struct skinny_req *req, struct skinnysession *s) 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, "Skinny/%s@%s", l->name, d->name); + ast_devstate_changed(AST_DEVICE_UNAVAILABLE, AST_DEVSTATE_CACHABLE, "Skinny/%s@%s", l->name, d->name); } } } @@ -5321,7 +5321,7 @@ static int handle_stimulus_message(struct skinny_req *req, struct skinnysession ast_verb(1, "RECEIVED UNKNOWN STIMULUS: %d(%d/%d)\n", event, instance, callreference); break; } - ast_devstate_changed(AST_DEVICE_UNKNOWN, "Skinny/%s@%s", l->name, d->name); + ast_devstate_changed(AST_DEVICE_UNKNOWN, AST_DEVSTATE_CACHABLE, "Skinny/%s@%s", l->name, d->name); return 1; } @@ -5372,7 +5372,7 @@ static int handle_offhook_message(struct skinny_req *req, struct skinnysession * transmit_ringer_mode(d, SKINNY_RING_OFF); l->hookstate = SKINNY_OFFHOOK; - ast_devstate_changed(AST_DEVICE_INUSE, "Skinny/%s@%s", l->name, d->name); + ast_devstate_changed(AST_DEVICE_INUSE, AST_DEVSTATE_CACHABLE, "Skinny/%s@%s", l->name, d->name); if (sub && sub->onhold) { return 1; @@ -5448,7 +5448,7 @@ static int handle_onhook_message(struct skinny_req *req, struct skinnysession *s return 0; } - ast_devstate_changed(AST_DEVICE_NOT_INUSE, "Skinny/%s@%s", l->name, d->name); + ast_devstate_changed(AST_DEVICE_NOT_INUSE, AST_DEVSTATE_CACHABLE, "Skinny/%s@%s", l->name, d->name); if (sub->onhold) { return 0; @@ -5834,7 +5834,7 @@ static int handle_soft_key_event_message(struct skinny_req *req, struct skinnyse return 0; } - ast_devstate_changed(AST_DEVICE_INUSE, "Skinny/%s@%s", l->name, d->name); + ast_devstate_changed(AST_DEVICE_INUSE, AST_DEVSTATE_CACHABLE, "Skinny/%s@%s", l->name, d->name); switch(event) { case SOFTKEY_NONE: @@ -6049,7 +6049,7 @@ static int handle_soft_key_event_message(struct skinny_req *req, struct skinnyse transmit_callstate(d, l->instance, sub->callid, l->hookstate); } - ast_devstate_changed(AST_DEVICE_NOT_INUSE, "Skinny/%s@%s", l->name, d->name); + ast_devstate_changed(AST_DEVICE_NOT_INUSE, AST_DEVSTATE_CACHABLE, "Skinny/%s@%s", l->name, d->name); if (skinnydebug) ast_verb(1, "Skinny %s@%s went on hook\n", l->name, d->name); if (l->transfer && sub->xferor && sub->owner->_state >= AST_STATE_RING) { @@ -6073,7 +6073,7 @@ static int handle_soft_key_event_message(struct skinny_req *req, struct skinnyse } } if ((l->hookstate == SKINNY_ONHOOK) && (AST_LIST_NEXT(sub, list) && !AST_LIST_NEXT(sub, list)->rtp)) { - ast_devstate_changed(AST_DEVICE_NOT_INUSE, "Skinny/%s@%s", l->name, d->name); + ast_devstate_changed(AST_DEVICE_NOT_INUSE, AST_DEVSTATE_CACHABLE, "Skinny/%s@%s", l->name, d->name); } } break; diff --git a/funcs/func_devstate.c b/funcs/func_devstate.c index e1f34387a1..6472610c8a 100644 --- a/funcs/func_devstate.c +++ b/funcs/func_devstate.c @@ -132,7 +132,7 @@ static int devstate_write(struct ast_channel *chan, const char *cmd, char *data, ast_db_put(astdb_family, data, value); - ast_devstate_changed(state_val, "Custom:%s", data); + ast_devstate_changed(state_val, AST_DEVSTATE_CACHABLE, "Custom:%s", data); return 0; } @@ -295,7 +295,7 @@ static char *handle_cli_devstate_change(struct ast_cli_entry *e, int cmd, struct ast_db_put(astdb_family, dev, state); - ast_devstate_changed(state_val, "Custom:%s", dev); + ast_devstate_changed(state_val, AST_DEVSTATE_CACHABLE, "Custom:%s", dev); return CLI_SUCCESS; } @@ -341,7 +341,7 @@ static int load_module(void) if (dev_name <= (const char *) 1) continue; ast_devstate_changed(ast_devstate_val(db_entry->data), - "Custom:%s\n", dev_name); + AST_DEVSTATE_CACHABLE, "Custom:%s\n", dev_name); } ast_db_freetree(db_tree); db_tree = NULL; diff --git a/include/asterisk/channel.h b/include/asterisk/channel.h index d5aa046af3..f245b62d49 100644 --- a/include/asterisk/channel.h +++ b/include/asterisk/channel.h @@ -938,6 +938,12 @@ enum { * some non-traditional dialplans (like AGI) to continue to function. */ AST_FLAG_DISABLE_WORKAROUNDS = (1 << 20), + /*! Disable device state event caching. This allows allows channel + * drivers to selectively prevent device state events from being cached + * by certain channels such as anonymous calls which have no persistent + * represenatation that can be tracked. + */ + AST_FLAG_DISABLE_DEVSTATE_CACHE = (1 << 21), }; /*! \brief ast_bridge_config flags */ diff --git a/include/asterisk/devicestate.h b/include/asterisk/devicestate.h index 66ca2bd1a3..86740bc2fd 100644 --- a/include/asterisk/devicestate.h +++ b/include/asterisk/devicestate.h @@ -61,6 +61,14 @@ enum ast_device_state { AST_DEVICE_TOTAL, /*/ Total num of device states, used for testing */ }; +/*! \brief Device State Cachability + * \note This is used to define the cachability of a device state when set. + */ +enum ast_devstate_cache { + AST_DEVSTATE_NOT_CACHABLE, /*!< This device state is not cachable */ + AST_DEVSTATE_CACHABLE, /*!< This device state is cachable */ +}; + /*! \brief Devicestate provider call back */ typedef enum ast_device_state (*ast_devstate_prov_cb_type)(const char *data); @@ -129,6 +137,7 @@ enum ast_device_state ast_device_state(const char *device); * \brief Tells Asterisk the State for Device is changed * * \param state the new state of the device + * \param cachable whether this device state is cachable * \param fmt device name like a dial string with format parameters * * The new state of the device will be sent off to any subscribers @@ -138,13 +147,14 @@ enum ast_device_state ast_device_state(const char *device); * \retval 0 on success * \retval -1 on failure */ -int ast_devstate_changed(enum ast_device_state state, const char *fmt, ...) - __attribute__((format(printf, 2, 3))); +int ast_devstate_changed(enum ast_device_state state, enum ast_devstate_cache cachable, const char *fmt, ...) + __attribute__((format(printf, 3, 4))); /*! * \brief Tells Asterisk the State for Device is changed * * \param state the new state of the device + * \param cachable whether this device state is cachable * \param device device name like a dial string with format parameters * * The new state of the device will be sent off to any subscribers @@ -154,7 +164,7 @@ int ast_devstate_changed(enum ast_device_state state, const char *fmt, ...) * \retval 0 on success * \retval -1 on failure */ -int ast_devstate_changed_literal(enum ast_device_state state, const char *device); +int ast_devstate_changed_literal(enum ast_device_state state, enum ast_devstate_cache cachable, const char *device); /*! * \brief Tells Asterisk the State for Device is changed. diff --git a/include/asterisk/event_defs.h b/include/asterisk/event_defs.h index 073d67bc6b..c385bcf79d 100644 --- a/include/asterisk/event_defs.h +++ b/include/asterisk/event_defs.h @@ -283,8 +283,14 @@ enum ast_event_ie_type { AST_EVENT_IE_CHALLENGE = 0x0032, AST_EVENT_IE_RESPONSE = 0x0033, AST_EVENT_IE_EXPECTED_RESPONSE = 0x0034, + /*! + * \brief Event non-cachability flag + * Used by: All events + * Payload type: UINT + */ + AST_EVENT_IE_CACHABLE = 0x0035, /*! \brief Must be the last IE value +1 */ - AST_EVENT_IE_TOTAL = 0x0035, + AST_EVENT_IE_TOTAL = 0x0036, }; /*! diff --git a/main/channel.c b/main/channel.c index 00f3bbb342..50ed55c131 100644 --- a/main/channel.c +++ b/main/channel.c @@ -299,6 +299,7 @@ static void channel_data_add_flags(struct ast_data *tree, ast_data_add_bool(tree, "BRIDGE_HANGUP_RUN", ast_test_flag(chan, AST_FLAG_BRIDGE_HANGUP_RUN)); ast_data_add_bool(tree, "BRIDGE_HANGUP_DONT", ast_test_flag(chan, AST_FLAG_BRIDGE_HANGUP_DONT)); ast_data_add_bool(tree, "DISABLE_WORKAROUNDS", ast_test_flag(chan, AST_FLAG_DISABLE_WORKAROUNDS)); + ast_data_add_bool(tree, "DISABLE_DEVSTATE_CACHE", ast_test_flag(chan, AST_FLAG_DISABLE_DEVSTATE_CACHE)); } #if defined(KEEP_TILL_CHANNEL_PARTY_NUMBER_INFO_NEEDED) @@ -2519,7 +2520,7 @@ static void ast_channel_destructor(void *obj) * instance is dead, we don't know the state of all other possible * instances. */ - ast_devstate_changed_literal(AST_DEVICE_UNKNOWN, device_name); + ast_devstate_changed_literal(AST_DEVICE_UNKNOWN, (chan->flags & AST_FLAG_DISABLE_DEVSTATE_CACHE ? AST_DEVSTATE_NOT_CACHABLE : AST_DEVSTATE_CACHABLE), device_name); } ast_atomic_fetchadd_int(&chancount, -1); } @@ -7058,7 +7059,7 @@ int ast_setstate(struct ast_channel *chan, enum ast_channel_state state) /* We have to pass AST_DEVICE_UNKNOWN here because it is entirely possible that the channel driver * for this channel is using the callback method for device state. If we pass in an actual state here * we override what they are saying the state is and things go amuck. */ - ast_devstate_changed_literal(AST_DEVICE_UNKNOWN, name); + ast_devstate_changed_literal(AST_DEVICE_UNKNOWN, (chan->flags & AST_FLAG_DISABLE_DEVSTATE_CACHE ? AST_DEVSTATE_NOT_CACHABLE : AST_DEVSTATE_CACHABLE), name); /* setstate used to conditionally report Newchannel; this is no more */ ast_manager_event(chan, EVENT_FLAG_CALL, "Newstate", diff --git a/main/devicestate.c b/main/devicestate.c index 84eedc81c5..aabf806e74 100644 --- a/main/devicestate.c +++ b/main/devicestate.c @@ -174,6 +174,7 @@ static AST_RWLIST_HEAD_STATIC(devstate_provs, devstate_prov); struct state_change { AST_LIST_ENTRY(state_change) list; + enum ast_devstate_cache cachable; char device[1]; }; @@ -191,6 +192,7 @@ struct devstate_change { AST_LIST_ENTRY(devstate_change) entry; uint32_t state; struct ast_eid eid; + enum ast_devstate_cache cachable; char device[1]; }; @@ -424,7 +426,7 @@ static int getproviderstate(const char *provider, const char *address) return res; } -static void devstate_event(const char *device, enum ast_device_state state) +static void devstate_event(const char *device, enum ast_device_state state, int cachable) { struct ast_event *event; enum ast_event_type event_type; @@ -440,18 +442,23 @@ static void devstate_event(const char *device, enum ast_device_state state) ast_debug(3, "device '%s' state '%d'\n", device, state); if (!(event = ast_event_new(event_type, - AST_EVENT_IE_DEVICE, AST_EVENT_IE_PLTYPE_STR, device, - AST_EVENT_IE_STATE, AST_EVENT_IE_PLTYPE_UINT, state, - AST_EVENT_IE_END))) { + AST_EVENT_IE_DEVICE, AST_EVENT_IE_PLTYPE_STR, device, + AST_EVENT_IE_STATE, AST_EVENT_IE_PLTYPE_UINT, state, + AST_EVENT_IE_CACHABLE, AST_EVENT_IE_PLTYPE_UINT, cachable, + AST_EVENT_IE_END))) { return; } - ast_event_queue_and_cache(event); + if (cachable) { + ast_event_queue_and_cache(event); + } else { + ast_event_queue(event); + } } /*! Called by the state change thread to find out what the state is, and then * to queue up the state change event */ -static void do_state_change(const char *device) +static void do_state_change(const char *device, int cachable) { enum ast_device_state state; @@ -459,10 +466,10 @@ static void do_state_change(const char *device) ast_debug(3, "Changing state for %s - state %d (%s)\n", device, state, ast_devstate2str(state)); - devstate_event(device, state); + devstate_event(device, state, cachable); } -int ast_devstate_changed_literal(enum ast_device_state state, const char *device) +int ast_devstate_changed_literal(enum ast_device_state state, enum ast_devstate_cache cachable, const char *device) { struct state_change *change; @@ -483,14 +490,15 @@ int ast_devstate_changed_literal(enum ast_device_state state, const char *device */ if (state != AST_DEVICE_UNKNOWN) { - devstate_event(device, state); + devstate_event(device, state, cachable); } else if (change_thread == AST_PTHREADT_NULL || !(change = ast_calloc(1, sizeof(*change) + strlen(device)))) { /* we could not allocate a change struct, or */ /* there is no background thread, so process the change now */ - do_state_change(device); + do_state_change(device, cachable); } else { /* queue the change */ strcpy(change->device, device); + change->cachable = cachable; AST_LIST_LOCK(&state_changes); AST_LIST_INSERT_TAIL(&state_changes, change, list); ast_cond_signal(&change_pending); @@ -502,10 +510,10 @@ int ast_devstate_changed_literal(enum ast_device_state state, const char *device int ast_device_state_changed_literal(const char *dev) { - return ast_devstate_changed_literal(AST_DEVICE_UNKNOWN, dev); + return ast_devstate_changed_literal(AST_DEVICE_UNKNOWN, AST_DEVSTATE_CACHABLE, dev); } -int ast_devstate_changed(enum ast_device_state state, const char *fmt, ...) +int ast_devstate_changed(enum ast_device_state state, enum ast_devstate_cache cachable, const char *fmt, ...) { char buf[AST_MAX_EXTENSION]; va_list ap; @@ -514,7 +522,7 @@ int ast_devstate_changed(enum ast_device_state state, const char *fmt, ...) vsnprintf(buf, sizeof(buf), fmt, ap); va_end(ap); - return ast_devstate_changed_literal(state, buf); + return ast_devstate_changed_literal(state, cachable, buf); } int ast_device_state_changed(const char *fmt, ...) @@ -526,7 +534,7 @@ int ast_device_state_changed(const char *fmt, ...) vsnprintf(buf, sizeof(buf), fmt, ap); va_end(ap); - return ast_devstate_changed_literal(AST_DEVICE_UNKNOWN, buf); + return ast_devstate_changed_literal(AST_DEVICE_UNKNOWN, AST_DEVSTATE_CACHABLE, buf); } /*! \brief Go through the dev state change queue and update changes in the dev state thread */ @@ -546,7 +554,7 @@ static void *do_devstate_changes(void *data) /* Process each state change */ while ((current = next)) { next = AST_LIST_NEXT(current, list); - do_state_change(current->device); + do_state_change(current->device, current->cachable); ast_free(current); } } @@ -590,7 +598,7 @@ static void devstate_cache_cb(const struct ast_event *event, void *data) collection->num_states++; } -static void process_collection(const char *device, struct change_collection *collection) +static void process_collection(const char *device, enum ast_devstate_cache cachable, struct change_collection *collection) { int i; struct ast_devstate_aggregate agg; @@ -641,7 +649,11 @@ static void process_collection(const char *device, struct change_collection *col return; } - ast_event_queue_and_cache(event); + if (cachable) { + ast_event_queue_and_cache(event); + } else { + ast_event_queue(event); + } } static void handle_devstate_change(struct devstate_change *sc) @@ -667,7 +679,7 @@ static void handle_devstate_change(struct devstate_change *sc) /* Populate the collection of device states from the cache */ ast_event_dump_cache(tmp_sub); - process_collection(sc->device, &collection); + process_collection(sc->device, sc->cachable, &collection); ast_event_sub_destroy(tmp_sub); } @@ -696,10 +708,12 @@ static void devstate_change_collector_cb(const struct ast_event *event, void *da const char *device; const struct ast_eid *eid; uint32_t state; + enum ast_devstate_cache cachable = AST_DEVSTATE_CACHABLE; device = ast_event_get_ie_str(event, AST_EVENT_IE_DEVICE); eid = ast_event_get_ie_raw(event, AST_EVENT_IE_EID); state = ast_event_get_ie_uint(event, AST_EVENT_IE_STATE); + cachable = ast_event_get_ie_uint(event, AST_EVENT_IE_CACHABLE); if (ast_strlen_zero(device) || !eid) { ast_log(LOG_ERROR, "Invalid device state change event received\n"); @@ -712,6 +726,7 @@ static void devstate_change_collector_cb(const struct ast_event *event, void *da strcpy(sc->device, device); sc->eid = *eid; sc->state = state; + sc->cachable = cachable; ast_mutex_lock(&devstate_collector.lock); AST_LIST_INSERT_TAIL(&devstate_collector.devstate_change_q, sc, entry); diff --git a/main/event.c b/main/event.c index 328dc1e7a4..85136c5e18 100644 --- a/main/event.c +++ b/main/event.c @@ -268,6 +268,7 @@ static const struct ie_map { [AST_EVENT_IE_CHALLENGE] = { AST_EVENT_IE_PLTYPE_STR, "Challenge" }, [AST_EVENT_IE_RESPONSE] = { AST_EVENT_IE_PLTYPE_STR, "Response" }, [AST_EVENT_IE_EXPECTED_RESPONSE] = { AST_EVENT_IE_PLTYPE_STR, "ExpectedResponse" }, + [AST_EVENT_IE_CACHABLE] = { AST_EVENT_IE_PLTYPE_UINT, "Cachable" }, }; const char *ast_event_get_type_name(const struct ast_event *event) diff --git a/main/features.c b/main/features.c index 2f08a989c5..00edb768d6 100644 --- a/main/features.c +++ b/main/features.c @@ -1094,7 +1094,7 @@ static void notify_metermaids(const char *exten, char *context, enum ast_device_ ast_debug(4, "Notification of state change to metermaids %s@%s\n to state '%s'", exten, context, ast_devstate2str(state)); - ast_devstate_changed(state, "park:%s@%s", exten, context); + ast_devstate_changed(state, AST_DEVSTATE_CACHABLE, "park:%s@%s", exten, context); } /*! \brief metermaids callback from devicestate.c */ diff --git a/res/res_calendar.c b/res/res_calendar.c index 959c0493f4..7c8518b85a 100644 --- a/res/res_calendar.c +++ b/res/res_calendar.c @@ -575,9 +575,9 @@ static struct ast_calendar_event *destroy_event(struct ast_calendar_event *event * but haven't hit the end event yet, go ahead and set the devicestate to the current busy status */ if (event->bs_start_sched < 0 && event->bs_end_sched >= 0) { if (!calendar_is_busy(event->owner)) { - ast_devstate_changed(AST_DEVICE_NOT_INUSE, "Calendar:%s", event->owner->name); + ast_devstate_changed(AST_DEVICE_NOT_INUSE, AST_DEVSTATE_CACHABLE, "Calendar:%s", event->owner->name); } else { - ast_devstate_changed(AST_DEVICE_BUSY, "Calendar:%s", event->owner->name); + ast_devstate_changed(AST_DEVICE_BUSY, AST_DEVSTATE_CACHABLE, "Calendar:%s", event->owner->name); } } @@ -818,9 +818,9 @@ static int calendar_devstate_change(const void *data) /* We can have overlapping events, so ignore the event->busy_state and check busy state * based on all events in the calendar */ if (!calendar_is_busy(event->owner)) { - ast_devstate_changed(AST_DEVICE_NOT_INUSE, "Calendar:%s", event->owner->name); + ast_devstate_changed(AST_DEVICE_NOT_INUSE, AST_DEVSTATE_CACHABLE, "Calendar:%s", event->owner->name); } else { - ast_devstate_changed(AST_DEVICE_BUSY, "Calendar:%s", event->owner->name); + ast_devstate_changed(AST_DEVICE_BUSY, AST_DEVSTATE_CACHABLE, "Calendar:%s", event->owner->name); } event = ast_calendar_unref_event(event); diff --git a/res/res_jabber.c b/res/res_jabber.c index 290cedca44..a00b8fe99c 100644 --- a/res/res_jabber.c +++ b/res/res_jabber.c @@ -349,7 +349,7 @@ static char *aji_cli_create_leafnode(struct ast_cli_entry *e, int cmd, static void aji_create_affiliations(struct aji_client *client, const char *node); static iks* aji_pubsub_iq_create(struct aji_client *client, const char *type); static void aji_publish_device_state(struct aji_client *client, const char * device, - const char *device_state); + const char *device_state, unsigned int cachable); static int aji_handle_pubsub_error(void *data, ikspak *pak); static int aji_handle_pubsub_event(void *data, ikspak *pak); static void aji_pubsub_subscribe(struct aji_client *client, const char *node); @@ -363,7 +363,7 @@ static void aji_publish_mwi(struct aji_client *client, const char *mailbox, static void aji_devstate_cb(const struct ast_event *ast_event, void *data); static void aji_mwi_cb(const struct ast_event *ast_event, void *data); static iks* aji_build_publish_skeleton(struct aji_client *client, const char *node, - const char *event_type); + const char *event_type, unsigned int cachable); /* No transports in this version */ /* static int aji_create_transport(char *label, struct aji_client *client); @@ -3207,6 +3207,7 @@ static void aji_devstate_cb(const struct ast_event *ast_event, void *data) { const char *device; const char *device_state; + unsigned int cachable; struct aji_client *client; if (ast_eid_cmp(&ast_eid_default, ast_event_get_ie_raw(ast_event, AST_EVENT_IE_EID))) { @@ -3218,7 +3219,8 @@ static void aji_devstate_cb(const struct ast_event *ast_event, void *data) client = ASTOBJ_REF((struct aji_client *) data); device = ast_event_get_ie_str(ast_event, AST_EVENT_IE_DEVICE); device_state = ast_devstate_str(ast_event_get_ie_uint(ast_event, AST_EVENT_IE_STATE)); - aji_publish_device_state(client, device, device_state); + cachable = ast_event_get_ie_uint(ast_event, AST_EVENT_IE_CACHABLE); + aji_publish_device_state(client, device, device_state, cachable); ASTOBJ_UNREF(client, ast_aji_client_destroy); } @@ -3258,11 +3260,13 @@ static void aji_init_event_distribution(struct aji_client *client) */ static int aji_handle_pubsub_event(void *data, ikspak *pak) { - char *item_id, *device_state, *context; + char *item_id, *device_state, *context, *cachable_str; int oldmsgs, newmsgs; iks *item, *item_content; struct ast_eid pubsub_eid; struct ast_event *event; + unsigned int cachable = AST_DEVSTATE_CACHABLE; + item = iks_find(iks_find(iks_find(pak->x, "event"), "items"), "item"); if (!item) { ast_log(LOG_ERROR, "Could not parse incoming PubSub event\n"); @@ -3277,11 +3281,14 @@ static int aji_handle_pubsub_event(void *data, ikspak *pak) } if (!strcasecmp(iks_name(item_content), "state")) { device_state = iks_find_cdata(item, "state"); + if ((cachable_str = iks_find_cdata(item, "cachable"))) { + sscanf(cachable_str, "%30d", &cachable); + } if (!(event = ast_event_new(AST_EVENT_DEVICE_STATE_CHANGE, - AST_EVENT_IE_DEVICE, AST_EVENT_IE_PLTYPE_STR, item_id, AST_EVENT_IE_STATE, - AST_EVENT_IE_PLTYPE_UINT, ast_devstate_val(device_state), AST_EVENT_IE_EID, - AST_EVENT_IE_PLTYPE_RAW, &pubsub_eid, sizeof(pubsub_eid), - AST_EVENT_IE_END))) { + AST_EVENT_IE_DEVICE, AST_EVENT_IE_PLTYPE_STR, item_id, AST_EVENT_IE_STATE, + AST_EVENT_IE_PLTYPE_UINT, ast_devstate_val(device_state), AST_EVENT_IE_EID, + AST_EVENT_IE_PLTYPE_RAW, &pubsub_eid, sizeof(pubsub_eid), + AST_EVENT_IE_END))) { return IKS_FILTER_EAT; } } else if (!strcasecmp(iks_name(item_content), "mailbox")) { @@ -3301,7 +3308,13 @@ static int aji_handle_pubsub_event(void *data, ikspak *pak) iks_name(item_content)); return IKS_FILTER_EAT; } - ast_event_queue_and_cache(event); + + if (cachable == AST_DEVSTATE_CACHABLE) { + ast_event_queue_and_cache(event); + } else { + ast_event_queue(event); + } + return IKS_FILTER_EAT; } @@ -3376,7 +3389,7 @@ static void aji_pubsub_subscribe(struct aji_client *client, const char *node) * \return iks * */ static iks* aji_build_publish_skeleton(struct aji_client *client, const char *node, - const char *event_type) + const char *event_type, unsigned int cachable) { iks *request = aji_pubsub_iq_create(client, "set"); iks *pubsub, *publish, *item; @@ -3390,8 +3403,24 @@ static iks* aji_build_publish_skeleton(struct aji_client *client, const char *no } item = iks_insert(publish, "item"); iks_insert_attrib(item, "id", node); - return item; + if (cachable == AST_DEVSTATE_NOT_CACHABLE) { + iks *options, *x, *field_form_type, *field_persist; + + options = iks_insert(pubsub, "publish-options"); + x = iks_insert(options, "x"); + iks_insert_attrib(x, "xmlns", "jabber:x:data"); + iks_insert_attrib(x, "type", "submit"); + field_form_type = iks_insert(x, "field"); + iks_insert_attrib(field_form_type, "var", "FORM_TYPE"); + iks_insert_attrib(field_form_type, "type", "hidden"); + iks_insert_cdata(iks_insert(field_form_type, "value"), "http://jabber.org/protocol/pubsub#publish-options", 0); + field_persist = iks_insert(x, "field"); + iks_insert_attrib(field_persist, "var", "pubsub#persist_items"); + iks_insert_cdata(iks_insert(field_persist, "value"), "0", 1); + } + + return item; } /*! @@ -3402,11 +3431,11 @@ static iks* aji_build_publish_skeleton(struct aji_client *client, const char *no * \return void */ static void aji_publish_device_state(struct aji_client *client, const char *device, - const char *device_state) + const char *device_state, unsigned int cachable) { - iks *request = aji_build_publish_skeleton(client, device, "device_state"); + iks *request = aji_build_publish_skeleton(client, device, "device_state", cachable); iks *state; - char eid_str[20]; + char eid_str[20], cachable_str[2]; if (ast_test_flag(&pubsubflags, AJI_PUBSUB_AUTOCREATE)) { if (ast_test_flag(&pubsubflags, AJI_XEP0248)) { aji_create_pubsub_node(client, "leaf", device, "device_state"); @@ -3418,6 +3447,8 @@ static void aji_publish_device_state(struct aji_client *client, const char *devi state = iks_insert(request, "state"); iks_insert_attrib(state, "xmlns", "http://asterisk.org"); iks_insert_attrib(state, "eid", eid_str); + snprintf(cachable_str, sizeof(cachable_str), "%u", cachable); + iks_insert_attrib(state, "cachable", cachable_str); iks_insert_cdata(state, device_state, strlen(device_state)); ast_aji_send(client, iks_root(request)); iks_delete(request); @@ -3437,7 +3468,7 @@ static void aji_publish_mwi(struct aji_client *client, const char *mailbox, char eid_str[20]; iks *mailbox_node, *request; snprintf(full_mailbox, sizeof(full_mailbox), "%s@%s", mailbox, context); - request = aji_build_publish_skeleton(client, full_mailbox, "message_waiting"); + request = aji_build_publish_skeleton(client, full_mailbox, "message_waiting", 1); ast_eid_to_str(eid_str, sizeof(eid_str), &ast_eid_default); mailbox_node = iks_insert(request, "mailbox"); iks_insert_attrib(mailbox_node, "xmlns", "http://asterisk.org");