|
|
|
|
@ -964,6 +964,7 @@ struct sip_auth {
|
|
|
|
|
#define SIP_PAGE2_RTCACHEFRIENDS (1 << 0) /*!< GP: Should we keep RT objects in memory for extended time? */
|
|
|
|
|
#define SIP_PAGE2_RTAUTOCLEAR (1 << 2) /*!< GP: Should we clean memory from peers after expiry? */
|
|
|
|
|
/* Space for addition of other realtime flags in the future */
|
|
|
|
|
#define SIP_PAGE2_STATECHANGEQUEUE (1 << 9) /*!< D: Unsent state pending change exists */
|
|
|
|
|
|
|
|
|
|
#define SIP_PAGE2_VIDEOSUPPORT (1 << 14) /*!< DP: Video supported if offered? */
|
|
|
|
|
#define SIP_PAGE2_TEXTSUPPORT (1 << 15) /*!< GDP: Global text enable */
|
|
|
|
|
@ -1262,7 +1263,7 @@ struct sip_pvt {
|
|
|
|
|
int noncecount; /*!< Nonce-count */
|
|
|
|
|
char lastmsg[256]; /*!< Last Message sent/received */
|
|
|
|
|
int amaflags; /*!< AMA Flags */
|
|
|
|
|
int pendinginvite; /*!< Any pending invite ? (seqno of this) */
|
|
|
|
|
int pendinginvite; /*!< Any pending INVITE or state NOTIFY (in subscribe pvt's) ? (seqno of this) */
|
|
|
|
|
struct sip_request initreq; /*!< Latest request that opened a new transaction
|
|
|
|
|
within this dialog.
|
|
|
|
|
NOT the request that opened the dialog
|
|
|
|
|
@ -8752,6 +8753,8 @@ static int transmit_state_notify(struct sip_pvt *p, int state, int full, int tim
|
|
|
|
|
add_header_contentLength(&req, tmp->used);
|
|
|
|
|
add_line(&req, tmp->str);
|
|
|
|
|
|
|
|
|
|
p->pendinginvite = p->ocseq; /* Remember that we have a pending NOTIFY in order not to confuse the NOTIFY subsystem */
|
|
|
|
|
|
|
|
|
|
return send_request(p, &req, XMIT_RELIABLE, p->ocseq);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@ -9992,10 +9995,17 @@ static int cb_extensionstate(char *context, char* exten, int state, void *data)
|
|
|
|
|
p->laststate = state;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
if (p->subscribed != NONE) /* Only send state NOTIFY if we know the format */
|
|
|
|
|
transmit_state_notify(p, state, 1, FALSE);
|
|
|
|
|
|
|
|
|
|
ast_verb(2, "Extension Changed %s new state %s for Notify User %s\n", exten, ast_extension_state2str(state), p->username);
|
|
|
|
|
if (p->subscribed != NONE) { /* Only send state NOTIFY if we know the format */
|
|
|
|
|
if (!p->pendinginvite) {
|
|
|
|
|
transmit_state_notify(p, state, 1, FALSE);
|
|
|
|
|
} else {
|
|
|
|
|
/* We already have a NOTIFY sent that is not answered. Queue the state up.
|
|
|
|
|
if many state changes happen meanwhile, we will only send a notification of the last one */
|
|
|
|
|
ast_set_flag(&p->flags[1], SIP_PAGE2_STATECHANGEQUEUE);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
ast_verb(2, "Extension Changed %s[%s] new state %s for Notify User %s %s\n", exten, context, ast_extension_state2str(state), p->username,
|
|
|
|
|
ast_test_flag(&p->flags[1], SIP_PAGE2_STATECHANGEQUEUE) ? "(queued)" : "");
|
|
|
|
|
|
|
|
|
|
sip_pvt_unlock(p);
|
|
|
|
|
|
|
|
|
|
@ -14873,6 +14883,10 @@ static void handle_response(struct sip_pvt *p, int resp, char *rest, struct sip_
|
|
|
|
|
else
|
|
|
|
|
__sip_ack(p, seqno, 0, sipmethod);
|
|
|
|
|
|
|
|
|
|
/* If this is a NOTIFY for a subscription clear the flag that indicates that we have a NOTIFY pending */
|
|
|
|
|
if (!p->owner && sipmethod == SIP_NOTIFY && p->pendinginvite)
|
|
|
|
|
p->pendinginvite = 0;
|
|
|
|
|
|
|
|
|
|
/* Get their tag if we haven't already */
|
|
|
|
|
if (ast_strlen_zero(p->theirtag) || (resp >= 200)) {
|
|
|
|
|
char tag[128];
|
|
|
|
|
@ -14931,6 +14945,11 @@ static void handle_response(struct sip_pvt *p, int resp, char *rest, struct sip_
|
|
|
|
|
} else {
|
|
|
|
|
if (p->subscribed == NONE)
|
|
|
|
|
p->needdestroy = 1;
|
|
|
|
|
if (ast_test_flag(&p->flags[1], SIP_PAGE2_STATECHANGEQUEUE)) {
|
|
|
|
|
/* Ready to send the next state we have on queue */
|
|
|
|
|
ast_clear_flag(&p->flags[1], SIP_PAGE2_STATECHANGEQUEUE);
|
|
|
|
|
cb_extensionstate((char *)p->context, (char *)p->exten, p->laststate, (void *) p);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} else if (sipmethod == SIP_REGISTER)
|
|
|
|
|
res = handle_response_register(p, resp, rest, req, seqno);
|
|
|
|
|
|