[Asterisk-Dev] SIP : transfer and display update
Roman Sidler
Roman.Sidler at ascom.ch
Fri Jun 10 17:46:26 MST 2005
Hello,
>>I'm confused in the way Asterisk handles the transfer with SIP.
>>Just say that A makes call to B, holds B, then makes call to C and make
the
>>transfer.
>>At the end B is in call with C.
>>On a SIP point of view, A sends a refer to Asterisk, with a refer-to
header
>>and replaces extension.
>>On receiving of this refer, Asterisk makes reinvite to B and reinvite to
C
>>with right sdp, so that B speaks to C.
>>The problem is that on its display, B is still with A, and C is still
with A
>>also.
>>Is there any way so that * handles refer in a different way?
The ReInvite you mentioned is to update the RTP-Stream SDP-Attribute "c="
If you configure canreinvite=no, there's is no update.
As part of our COLP extension (#ifdef COLP) we need an asynchroneous
solution, not only for SIP.
We send an AST_CONTROL_COLP frame into new bridge.
We used the "Remote-Party-ID" header field, also used by CISCO.
To change "from" and "to" Field is a bad idea, because one of them is
mostly the proxy address.
Another problem is to the differ callerid (origin) and colp (connected
peer).
I'm planning to make a patch for this, when it runs 100% over IAX and
Q.931, SIP to SIP is ok.
******chan_sip.c:attempt_transfer()-> the tricky part
...
#ifdef COLP
char **change_c = NULL;
char **change_d = NULL;
char *get_c = NULL;
char *get_d = NULL;
if (peerc->outgoing){
change_c = &peerc->callerid;
get_c = strdup(peerc->colp);
}
else {
change_c = &peerc->colp;
get_c = strdup(peerc->callerid);
}
if (peerd->outgoing) {
change_d = &peerd->callerid;
get_d = strdup(peerd->colp);
}
else {
change_d = &peerd->colp;
get_d = strdup(peerd->callerid);
}
if (!(*change_c && *change_d && get_c && get_d)) return res;
/*Notify to channels*/
struct ast_frame fc;
memset(&fc, 0, sizeof(fc));
fc.frametype = AST_FRAME_CONTROL;
fc.subclass = AST_CONTROL_COLP;
fc.data = get_c;
fc.datalen = strlen(get_c)+1;
struct ast_frame fd;
memset(&fd, 0, sizeof(fd));
fd.frametype = AST_FRAME_CONTROL;
fd.subclass = AST_CONTROL_COLP;
fd.data = get_d;
fd.datalen = strlen(get_d)+1;
#endif
if (ast_channel_masquerade(peerb, peerc)) {
ast_log(LOG_WARNING, "Failed to masquerade %s into %s\n",
peerb->name, peerc->name);
res = -1;
}
#ifdef COLP
/*note the order of masquerade and notifying COLP-frame*/
ast_queue_frame(peerb, &fc);/*peerb masqueraded by peerc*/
ast_queue_frame(peerd, &fd);/*peerd..*/
#endif
...
******in channel.c:ast_write()
...
case AST_FRAME_CONTROL:
#ifdef COLP
else if (fr->subclass == AST_CONTROL_COLP){
if (fr->data && fr->datalen && *((char*)fr->data)){
if (chan->outgoing){
if (chan->callerid)
free(chan->callerid);
chan->callerid = strdup(fr->data);
res = ast_indicate(chan, fr->subclass);
}
else{/*incoming*/
if (chan->colp)
free(chan->colp);
chan->colp = strdup(fr->data);
res = ast_indicate(chan, fr->subclass);
}
}
}
#endif
...
************chan.sip.c:sip_indicate()********
..
case AST_CONTROL_COLP:
if (ast->colp)
transmit_reinvite_with_sdp(p);
break;
..
Roman
More information about the asterisk-dev
mailing list