int callingpres; /*!< Calling id presentation */
int inUse; /*!< Number of calls in use */
int inRinging; /*!< Number of calls ringing */
+ int onHold; /*!< Peer has someone on hold */
int call_limit; /*!< Limit of concurrent calls */
enum transfermodes allowtransfer; /*! SIP Refer restriction scheme */
char vmexten[AST_MAX_EXTENSION]; /*!< Dialplan extension for MWI notify message*/
static int sip_poke_noanswer(void *data);
static int sip_poke_peer(struct sip_peer *peer);
static void sip_poke_all_peers(void);
-
+static void sip_peer_hold(struct sip_pvt *p, int hold);
/*--- Applications, functions, CLI and manager command helpers */
static const char *sip_nat_mode(const struct sip_pvt *p);
ast_set_read_format(p->owner, p->owner->readformat);
ast_set_write_format(p->owner, p->owner->writeformat);
}
+
+ bridgepeer = ast_bridged_channel(p->owner);
- if ((bridgepeer = ast_bridged_channel(p->owner))) {
- /* We have a bridge */
- /* Turn on/off music on hold if we are holding/unholding */
- if (sin.sin_addr.s_addr && !sendonly) {
+ /* Turn on/off music on hold if we are holding/unholding */
+ if (sin.sin_addr.s_addr && !sendonly) {
+ /* Update peer state */
+ sip_peer_hold(p, 0);
+ if (bridgepeer)
ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
- /* Activate a re-invite */
- ast_queue_frame(p->owner, &ast_null_frame);
- } else if (!sin.sin_addr.s_addr || sendonly) {
- /* No address for RTP, we're on hold */
+ /* Activate a re-invite */
+ ast_queue_frame(p->owner, &ast_null_frame);
+ } else if (!sin.sin_addr.s_addr || sendonly) {
+ /* Update peer state */
+ sip_peer_hold(p, 1);
+ /* No address for RTP, we're on hold */
+ if (bridgepeer)
ast_queue_control_data(p->owner, AST_CONTROL_HOLD,
- S_OR(p->mohsuggest, NULL),
- !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
-
- if (sendonly)
- ast_rtp_stop(p->rtp);
- /* RTCP needs to go ahead, even if we're on hold!!! */
-
- /* Activate a re-invite */
- ast_queue_frame(p->owner, &ast_null_frame);
- }
- /* guess we got a re-invite for changing media or IP - not hold/unhold */
+ S_OR(p->mohsuggest, NULL),
+ !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
+
+ if (sendonly)
+ ast_rtp_stop(p->rtp);
+ /* RTCP needs to go ahead, even if we're on hold!!! */
+
+ /* Activate a re-invite */
+ ast_queue_frame(p->owner, &ast_null_frame);
}
/* Manager Hold and Unhold events must be generated, if necessary */
pidfstate = "away";
pidfnote = "Unavailable";
break;
+ case AST_EXTENSION_ONHOLD:
+ break;
case AST_EXTENSION_NOT_INUSE:
default:
/* Default setting */
return AUTH_CHALLENGE_SENT;
}
+/*! \brief Change onhold state of a peer using a pvt structure */
+static void sip_peer_hold(struct sip_pvt *p, int hold)
+{
+ struct sip_peer *peer = find_peer(p->peername, NULL, 1);
+
+ if (!peer)
+ return;
+
+ /* If they put someone on hold, increment the value... otherwise decrement it */
+ if (hold)
+ peer->onHold++;
+ else
+ peer->onHold--;
+
+ /* Request device state update */
+ ast_device_state_changed("SIP/%s", peer->name);
+
+ return;
+}
+
/*! \brief Callback for the devicestate notification (SUBSCRIBE) support subsystem
\note If you add an "hint" priority to the extension in the dial plan,
you will get notifications on device state changes */
res = AST_DEVICE_INUSE;
else
res = AST_DEVICE_NOT_INUSE;
- if (p->inRinging) {
+ if (p->onHold)
+ res = AST_DEVICE_ONHOLD;
+ else if (p->inRinging) {
if (p->inRinging == p->inUse)
res = AST_DEVICE_RINGING;
else