[asterisk-dev] Call waiting the broadsoft way
Kevin Stewart
kevins at callplus.co.nz
Mon Mar 30 21:01:08 CDT 2009
I am trying to implement call waiting to devices that only support
server site Call waiting.
the phones reply busy to a second invite so you have to send them
sip_info messages of type
application/broadsoft with data "play tone CallWaitingTone1"
to stop it send
application/broadsoft with data "stop CallWaitingTone"
I have this working sort of working on 1.4.21.2 as per the patch below
I have added a struct to hold the other sip_pvt and the call waiting state.
call waiting is played if a user places an outbound call and then
receives a new inbound call (I think its broken if the user did not
originate the first call)
it stops on hang up so is a start.
How would I bridge the user and the new caller?
Have I put the original user on hold correctly?
Kevin
--- channels/chan_sip.c.orig 2008-08-26 09:38:08.000000000 +1200
+++ channels/chan_sip.c 2009-03-31 14:34:48.000000000 +1300
@@ -903,6 +903,19 @@
enum referstatus status; /*!< REFER status */
};
+/*!< KRS call waiting */
+enum cwstatus {
+ CW_IDLE,
+ CW_SENT,
+ CW_RINGING,
+ CW_HOLD
+};
+
+struct sip_cw {
+ enum cwstatus status;
+ struct sip_pvt *cwcall; /*!< pointer to the
other call in the cw pair */
+};
+
/*! \brief sip_pvt: PVT structures are used for each SIP dialog, ie. a
call, a registration, a subscribe */
static struct sip_pvt {
ast_mutex_t lock; /*!< Dialog private lock */
@@ -1019,6 +1032,8 @@
struct sip_pvt *next; /*!< Next dialog in chain */
struct sip_invite_param *options; /*!< Options for INVITE */
int autoframing;
+
+ struct sip_cw callwaiting; /*!< KRS call waiting */
} *iflist = NULL;
/*! Max entires in the history list for a sip_pvt */
@@ -1266,6 +1281,9 @@
static void parse_moved_contact(struct sip_pvt *p, struct sip_request
*req);
static int sip_send_mwi_to_peer(struct sip_peer *peer);
static int does_peer_need_mwi(struct sip_peer *peer);
+static int transmit_info_with_start_cwtone(struct sip_pvt *p,int cwtone);
+static int transmit_info_with_stop_cwtone(struct sip_pvt *p);
+static int transmit_info_with_flash(struct sip_pvt *p);
/*--- Dialog management */
static struct sip_pvt *sip_alloc(ast_string_field callid, struct
sockaddr_in *sin,
@@ -2955,10 +2973,14 @@
{
int res, xmitres = 0;
struct sip_pvt *p;
+ struct sip_pvt *q;
+ struct sip_user *u=NULL;
struct varshead *headp;
struct ast_var_t *current;
const char *referer = NULL; /* SIP refererer */
+ ast_verbose(VERBOSE_PREFIX_3 "KRS was here sip_call dest=%s,
exten=%s\n",dest,ast->exten);
+
p = ast->tech_pvt;
if ((ast->_state != AST_STATE_DOWN) && (ast->_state !=
AST_STATE_RESERVED)) {
ast_log(LOG_WARNING, "sip_call called on %s, neither
down nor reserved\n", ast->name);
@@ -3027,7 +3049,34 @@
p->t38.jointcapability = p->t38.capability;
if (option_debug > 1)
ast_log(LOG_DEBUG,"Our T38 capability
(%d), joint T38 capability (%d)\n", p->t38.capability,
p->t38.jointcapability);
- xmitres = transmit_invite(p, SIP_INVITE, 1, 2);
+
+ /* KRS call waiting */
+ ast_verbose(VERBOSE_PREFIX_3 "KRS find_user
%s\n",dest);
+ if((u=find_user(dest,1))){
+ ast_verbose(VERBOSE_PREFIX_3 "KRS code
inUse=%d\n",u->inUse);
+ }else{
+ ast_verbose(VERBOSE_PREFIX_3 "KRS cound
not find user %s\n",dest);
+ }
+ if((u=find_user(dest,1)) && u->inUse==1){
+ //ast_mutex_lock(&iflock);
+ for (q = iflist; q &&
strcmp(dest,q->username) ; q = q->next);
+ if(q) ast_mutex_lock(&q->lock);
+ //ast_mutex_unlock(&iflock);
+ if(q){
+ ast_verbose(VERBOSE_PREFIX_3
"KRS code p=%p q=%p\n",p,q);
+ q->callwaiting.status=CW_SENT;
+ q->callwaiting.cwcall=p;
+ p->callwaiting.status=CW_RINGING;
+ p->callwaiting.cwcall=q;
+ ast_mutex_unlock(&q->lock);
+ ast_verbose(VERBOSE_PREFIX_3
"KRS sending start_cwtone\n");
+ xmitres =
transmit_info_with_start_cwtone(q, 1);
+ }else{
+ xmitres = transmit_invite(p,
SIP_INVITE, 1, 2);
+ }
+ }else{
+ xmitres = transmit_invite(p, SIP_INVITE,
1, 2);
+ }
if (xmitres == XMIT_ERROR)
return -1; /* Transmission error */
@@ -3497,6 +3546,15 @@
return 0;
}
+ switch(p->callwaiting.status){
+ case CW_SENT:
+ transmit_info_with_stop_cwtone(p);
+ break;
+ case CW_IDLE:
+ default:
+ break;
+ }
+
if (ast_test_flag(&p->flags[0], SIP_DEFER_BYE_ON_TRANSFER)) {
if (ast_test_flag(&p->flags[0], SIP_INC_COUNT) ||
ast_test_flag(&p->flags[1], SIP_PAGE2_CALL_ONHOLD)) {
if (option_debug && sipdebug)
@@ -3971,6 +4029,9 @@
case AST_CONTROL_SRCUPDATE:
ast_rtp_new_source(p->rtp);
break;
+ case AST_CONTROL_FLASH:
+ transmit_info_with_flash(p);
+ break;
case -1:
res = -1;
break;
@@ -4456,6 +4517,11 @@
ast_mutex_init(&p->lock);
+
+ /* KRS call waiting */
+ p->callwaiting.status = CW_IDLE;
+ p->callwaiting.cwcall=NULL;
+
p->method = intended_method;
p->initid = -1;
p->waitid = -1;
@@ -7837,6 +7900,43 @@
return send_request(p, &req, XMIT_RELIABLE, p->ocseq);
}
+static int transmit_info_with_start_cwtone(struct sip_pvt *p,int cwtone)
+{
+ struct sip_request req;
+ char event[256];
+
+ sprintf(event,"play tone CallWaitingTone%i\r\n",cwtone);
+ reqprep(&req, p, SIP_INFO, 0, 1);
+ add_header(&req, "Content-Type", "application/broadsoft");
+ add_header_contentLength(&req, strlen(event));
+ add_line(&req, event);
+ return send_request(p, &req, XMIT_RELIABLE, p->ocseq);
+}
+
+static int transmit_info_with_stop_cwtone(struct sip_pvt *p)
+{
+ struct sip_request req;
+ char* event="stop CallWaitingTone\r\n";
+
+ reqprep(&req, p, SIP_INFO, 0, 1);
+ add_header(&req, "Content-Type", "application/broadsoft");
+ add_header_contentLength(&req, strlen(event));
+ add_line(&req, event);
+ return send_request(p, &req, XMIT_RELIABLE, p->ocseq);
+}
+
+static int transmit_info_with_flash(struct sip_pvt *p)
+{
+ struct sip_request req;
+ char* event="event flashhook\r\n";
+
+ reqprep(&req, p, SIP_INFO, 0, 1);
+ add_header(&req, "Content-Type", "application/broadsoft");
+ add_header_contentLength(&req, strlen(event));
+ add_line(&req, event);
+ return send_request(p, &req, XMIT_RELIABLE, p->ocseq);
+}
+
/*! \brief Send SIP INFO with video update request */
static int transmit_info_with_vidupdate(struct sip_pvt *p)
{
@@ -8714,7 +8814,9 @@
ast_rtp_codec_setpref(p->rtp, &peer->prefs);
p->autoframing = peer->autoframing;
}
- if (!ast_test_flag(&peer->flags[1], SIP_PAGE2_DYNAMIC)) {
+ //KRS allow hawawei to register non dynamic numbers
+ //if (!ast_test_flag(&peer->flags[1], SIP_PAGE2_DYNAMIC)) {
+ if (!ast_test_flag(&peer->flags[1], SIP_PAGE2_DYNAMIC)
&& 0) {
ast_log(LOG_ERROR, "Peer '%s' is trying to
register, but not configured as host=dynamic\n", peer->name);
res = AUTH_PEER_NOT_DYNAMIC;
} else {
@@ -11257,6 +11359,41 @@
ast_queue_control(p->owner, AST_CONTROL_VIDUPDATE);
transmit_response(p, "200 OK", req);
return;
+ } else if (!strcasecmp(c, "application/broadsoft")) {
+ //KRS flash for flash hook
+ if (!ast_strlen_zero(req->line[0]) &&
!strcasecmp(req->line[0], "event flashhook")){
+ struct ast_frame f = { AST_FRAME_CONTROL,
AST_CONTROL_FLASH, };
+ ast_verbose(VERBOSE_PREFIX_3 "KRS code p=%p\n",p);
+ switch(p->callwaiting.status){
+ case CW_IDLE:
+ ast_verbose(VERBOSE_PREFIX_3 "KRS %s
flash %d CW_IDLE:\n",p->uri,p->callwaiting.status);
+ break;
+ case CW_SENT:
+ ast_verbose(VERBOSE_PREFIX_3 "KRS %s
flash %d CW_SENT:\n",p->uri,p->callwaiting.status);
+
ast_queue_control(p->owner,AST_CONTROL_HOLD);
+ p->callwaiting.status = CW_HOLD;
+
ast_queue_control(p->callwaiting.cwcall->owner, AST_CONTROL_ANSWER);
+ break;
+ case CW_RINGING:
+ ast_verbose(VERBOSE_PREFIX_3 "KRS %s
flash %d CW_RINGING:\n",p->uri,p->callwaiting.status);
+ break;
+ case CW_HOLD:
+
ast_queue_control(p->owner,AST_CONTROL_UNHOLD);
+ ast_queue_frame(p->owner, &ast_null_frame);
+ change_hold_state(p, req, FALSE, 0);
+ ast_verbose(VERBOSE_PREFIX_3 "KRS %s
flash %d CW_HOLD:\n",p->uri,p->callwaiting.status);
+ break;
+ default:
+ ast_queue_frame(p->owner, &f);
+ if (sipdebug)
+ ast_verbose("*
handle_request_info event received: FLASH\n");
+ }
+ transmit_response(p, "200 OK", req);
+ }else{
+ ast_log(LOG_WARNING, "Unsupported INFO message
from %s. Content %s\n",p->callid, buf);
+ transmit_response(p, "415 Unsupported Media
Type", req);
+ }
+ return;
} else if (!ast_strlen_zero(c = get_header(req, "X-ClientCode"))) {
/* Client code (from SNOM phone) */
if (ast_test_flag(&p->flags[0], SIP_USECLIENTCODE)) {
Kevin Stewart
VOIP Network Engineer
Direct:
+64 9 919 6120
Mobile:
021 879057
Fax:
+64 9 919 6121
This message and any attachments contain privileged and confidential information. If you are not the intended recipient of
this message, you are hereby notified that any use, dissemination, distribution or reproduction of this message is prohibited.
If you have received this message in error please notify the sender immediately via email and then destroy this message
and any attachments.
More information about the asterisk-dev
mailing list