aboutsummaryrefslogtreecommitdiffstats
path: root/channels/chan_sip.c
diff options
context:
space:
mode:
authormarkster <markster@f38db490-d61c-443f-a65b-d21fe96a405b>2003-06-28 16:40:02 +0000
committermarkster <markster@f38db490-d61c-443f-a65b-d21fe96a405b>2003-06-28 16:40:02 +0000
commit63170c4333b792805df5170e43d516b479a75421 (patch)
tree350126d47aecc8eeeaca9794943d8d2640d37670 /channels/chan_sip.c
parentefde31a9908909b35ee154afe257030a56a6c520 (diff)
Add SIP/RTP video support, video enable app_echo, start on RTCP
git-svn-id: http://svn.digium.com/svn/asterisk/trunk@1128 f38db490-d61c-443f-a65b-d21fe96a405b
Diffstat (limited to 'channels/chan_sip.c')
-rwxr-xr-xchannels/chan_sip.c295
1 files changed, 229 insertions, 66 deletions
diff --git a/channels/chan_sip.c b/channels/chan_sip.c
index 6ff15bcac..35a506aeb 100755
--- a/channels/chan_sip.c
+++ b/channels/chan_sip.c
@@ -114,7 +114,7 @@ static pthread_t monitor_thread = 0;
static int restart_monitor(void);
/* Codecs that we support by default: */
-static int capability = AST_FORMAT_ULAW | AST_FORMAT_ALAW | AST_FORMAT_GSM;
+static int capability = AST_FORMAT_ULAW | AST_FORMAT_ALAW | AST_FORMAT_GSM | AST_FORMAT_H261;
static int noncodeccapability = AST_RTP_DTMF;
static char ourhost[256];
@@ -125,6 +125,8 @@ static int sipdebug = 0;
static int tos = 0;
+static int videosupport = 0;
+
static int globaldtmfmode = SIP_DTMF_RFC2833;
/* Expire slowly */
@@ -186,6 +188,7 @@ static struct sip_pvt {
int nat; /* Whether to try to support NAT */
struct sockaddr_in sa; /* Our peer */
struct sockaddr_in redirip; /* Where our RTP should be going if not to us */
+ struct sockaddr_in vredirip; /* Where our Video RTP should be going if not to us */
struct sockaddr_in recv; /* Received as */
struct in_addr ourip; /* Our IP */
struct ast_channel *owner; /* Who owns us */
@@ -233,6 +236,7 @@ static struct sip_pvt {
struct sip_peer *peerpoke; /* If this calls is to poke a peer, which one */
struct sip_registry *registry; /* If this is a REGISTER call, to which registry */
struct ast_rtp *rtp; /* RTP Session */
+ struct ast_rtp *vrtp; /* Video RTP session */
struct sip_pkt *packets; /* Packets scheduled for re-transmission */
struct sip_pvt *next;
} *iflist = NULL;
@@ -367,7 +371,7 @@ static int transmit_response_with_auth(struct sip_pvt *p, char *msg, struct sip_
static int transmit_request(struct sip_pvt *p, char *msg, int inc, int reliable);
static int transmit_request_with_auth(struct sip_pvt *p, char *msg, int inc, int reliable);
static int transmit_invite(struct sip_pvt *p, char *msg, int sendsdp, char *auth, char *vxml_url,char *distinctive_ring);
-static int transmit_reinvite_with_sdp(struct sip_pvt *p, struct ast_rtp *rtp);
+static int transmit_reinvite_with_sdp(struct sip_pvt *p, struct ast_rtp *rtp, struct ast_rtp *vrtp);
static int transmit_info_with_digit(struct sip_pvt *p, char digit);
static int transmit_message_with_text(struct sip_pvt *p, char *text);
static int transmit_refer(struct sip_pvt *p, char *dest);
@@ -612,6 +616,10 @@ static int create_addr(struct sip_pvt *r, char *peer)
ast_log(LOG_DEBUG, "Setting NAT on RTP to %d\n", r->nat);
ast_rtp_setnat(r->rtp, r->nat);
}
+ if (r->vrtp) {
+ ast_log(LOG_DEBUG, "Setting NAT on VRTP to %d\n", r->nat);
+ ast_rtp_setnat(r->vrtp, r->nat);
+ }
strncpy(r->peername, p->username, sizeof(r->peername)-1);
strncpy(r->peersecret, p->secret, sizeof(r->peersecret)-1);
strncpy(r->username, p->username, sizeof(r->username)-1);
@@ -761,6 +769,7 @@ static int sip_pref_append(int format)
static int sip_codec_choose(int formats)
{
struct sip_codec_pref *cur;
+ formats &= (AST_FORMAT_MAX_AUDIO - 1);
cur = prefs;
while(cur) {
if (formats & cur->codec)
@@ -828,6 +837,9 @@ static void __sip_destroy(struct sip_pvt *p, int lockowner)
if (p->rtp) {
ast_rtp_destroy(p->rtp);
}
+ if (p->vrtp) {
+ ast_rtp_destroy(p->vrtp);
+ }
if (p->route) {
free_old_route(p->route);
p->route = NULL;
@@ -965,31 +977,42 @@ static int sip_write(struct ast_channel *ast, struct ast_frame *frame)
{
struct sip_pvt *p = ast->pvt->pvt;
int res = 0;
- if (frame->frametype != AST_FRAME_VOICE) {
- if (frame->frametype == AST_FRAME_IMAGE)
- return 0;
- else {
- ast_log(LOG_WARNING, "Can't send %d type frames with SIP write\n", frame->frametype);
- return 0;
- }
- } else {
+ if (frame->frametype == AST_FRAME_VOICE) {
if (!(frame->subclass & ast->nativeformats)) {
ast_log(LOG_WARNING, "Asked to transmit frame type %d, while native formats is %d (read/write = %d/%d)\n",
frame->subclass, ast->nativeformats, ast->readformat, ast->writeformat);
return -1;
}
- }
- if (p) {
- ast_pthread_mutex_lock(&p->lock);
- if (p->rtp) {
- if ((ast->_state != AST_STATE_UP) && !p->progress && !p->outgoing) {
- transmit_response_with_sdp(p, "183 Session Progress", &p->initreq, 0);
- p->progress = 1;
+ if (p) {
+ ast_pthread_mutex_lock(&p->lock);
+ if (p->rtp) {
+ if ((ast->_state != AST_STATE_UP) && !p->progress && !p->outgoing) {
+ transmit_response_with_sdp(p, "183 Session Progress", &p->initreq, 0);
+ p->progress = 1;
+ }
+ res = ast_rtp_write(p->rtp, frame);
}
- res = ast_rtp_write(p->rtp, frame);
+ ast_pthread_mutex_unlock(&p->lock);
}
- ast_pthread_mutex_unlock(&p->lock);
+ } else if (frame->frametype == AST_FRAME_VIDEO) {
+ if (p) {
+ ast_pthread_mutex_lock(&p->lock);
+ if (p->vrtp) {
+ if ((ast->_state != AST_STATE_UP) && !p->progress && !p->outgoing) {
+ transmit_response_with_sdp(p, "183 Session Progress", &p->initreq, 0);
+ p->progress = 1;
+ }
+ res = ast_rtp_write(p->vrtp, frame);
+ }
+ ast_pthread_mutex_unlock(&p->lock);
+ }
+ } else if (frame->frametype == AST_FRAME_IMAGE) {
+ return 0;
+ } else {
+ ast_log(LOG_WARNING, "Can't send %d type frames with SIP write\n", frame->frametype);
+ return 0;
}
+
return res;
}
@@ -1109,6 +1132,11 @@ static struct ast_channel *sip_new(struct sip_pvt *i, int state, char *title)
ast_dsp_set_features(i->vad, DSP_FEATURE_DTMF_DETECT);
}
tmp->fds[0] = ast_rtp_fd(i->rtp);
+ tmp->fds[1] = ast_rtcp_fd(i->rtp);
+ if (i->vrtp) {
+ tmp->fds[2] = ast_rtp_fd(i->vrtp);
+ tmp->fds[3] = ast_rtcp_fd(i->vrtp);
+ }
ast_setstate(tmp, state);
if (state == AST_STATE_RING)
tmp->rings = 1;
@@ -1124,6 +1152,7 @@ static struct ast_channel *sip_new(struct sip_pvt *i, int state, char *title)
tmp->pvt->answer = sip_answer;
tmp->pvt->read = sip_read;
tmp->pvt->write = sip_write;
+ tmp->pvt->write_video = sip_write;
tmp->pvt->indicate = sip_indicate;
tmp->pvt->transfer = sip_transfer;
tmp->pvt->fixup = sip_fixup;
@@ -1245,12 +1274,27 @@ static char *get_header(struct sip_request *req, char *name)
return __get_header(req, name, &start);
}
-static struct ast_frame *sip_rtp_read(struct sip_pvt *p)
+static struct ast_frame *sip_rtp_read(struct ast_channel *ast, struct sip_pvt *p)
{
/* Retrieve audio/etc from channel. Assumes p->lock is already held. */
struct ast_frame *f;
static struct ast_frame null_frame = { AST_FRAME_NULL, };
- f = ast_rtp_read(p->rtp);
+ switch(ast->fdno) {
+ case 0:
+ f = ast_rtp_read(p->rtp);
+ break;
+ case 1:
+ f = ast_rtcp_read(p->rtp);
+ break;
+ case 2:
+ f = ast_rtp_read(p->vrtp);
+ break;
+ case 3:
+ f = ast_rtcp_read(p->vrtp);
+ break;
+ default:
+ f = &null_frame;
+ }
/* Don't send RFC2833 if we're not supposed to */
if (f && (f->frametype == AST_FRAME_DTMF) && !(p->dtmfmode & SIP_DTMF_RFC2833))
return &null_frame;
@@ -1276,7 +1320,7 @@ static struct ast_frame *sip_read(struct ast_channel *ast)
struct ast_frame *fr;
struct sip_pvt *p = ast->pvt->pvt;
ast_pthread_mutex_lock(&p->lock);
- fr = sip_rtp_read(p);
+ fr = sip_rtp_read(ast, p);
ast_pthread_mutex_unlock(&p->lock);
return fr;
}
@@ -1308,7 +1352,9 @@ static struct sip_pvt *sip_alloc(char *callid, struct sockaddr_in *sin, int useg
p->initid = -1;
p->autokillid = -1;
p->stateid = -1;
- p->rtp = ast_rtp_new(NULL, NULL);
+ p->rtp = ast_rtp_new(sched, io, 1, 0);
+ if (videosupport)
+ p->vrtp = ast_rtp_new(sched, io, 1, 0);
p->branch = rand();
p->tag = rand();
@@ -1320,17 +1366,18 @@ static struct sip_pvt *sip_alloc(char *callid, struct sockaddr_in *sin, int useg
return NULL;
}
ast_rtp_settos(p->rtp, tos);
+ if (p->vrtp)
+ ast_rtp_settos(p->vrtp, tos);
if (useglobalnat && sin) {
/* Setup NAT structure according to global settings if we have an address */
p->nat = globalnat;
memcpy(&p->recv, sin, sizeof(p->recv));
ast_rtp_setnat(p->rtp, p->nat);
+ if (p->vrtp)
+ ast_rtp_setnat(p->vrtp, p->nat);
}
ast_pthread_mutex_init(&p->lock);
-#if 0
- ast_rtp_set_data(p->rtp, p);
- ast_rtp_set_callback(p->rtp, rtpready);
-#endif
+
if (sin) {
memcpy(&p->sa, sin, sizeof(p->sa));
if (ast_ouraddrfor(&p->sa.sin_addr,&p->ourip))
@@ -1554,13 +1601,16 @@ static int process_sdp(struct sip_pvt *p, struct sip_request *req)
char *a;
char host[258];
int len = -1;
- int portno;
+ int portno=0;
+ int vportno=0;
int peercapability, peernoncodeccapability;
+ int vpeercapability, vpeernoncodeccapability;
struct sockaddr_in sin;
char *codecs;
struct hostent *hp;
int codec;
int iterator;
+ int x;
/* Get codec and RTP info from SDP */
if (strcasecmp(get_header(req, "Content-Type"), "application/sdp")) {
@@ -1583,51 +1633,85 @@ static int process_sdp(struct sip_pvt *p, struct sip_request *req)
ast_log(LOG_WARNING, "Unable to lookup host in c= line, '%s'\n", c);
return -1;
}
- if ((sscanf(m, "audio %d RTP/AVP %n", &portno, &len) != 1) || (len < 0)) {
- ast_log(LOG_WARNING, "Unable to determine port number for RTP in '%s'\n", m);
- return -1;
+ sdpLineNum_iterator_init(&iterator);
+ while ((m = get_sdp_iterate(&iterator, req, "m"))[0] != '\0') {
+ if ((sscanf(m, "audio %d RTP/AVP %n", &x, &len) == 1)) {
+ portno = x;
+ // Scan through the RTP payload types specified in a "m=" line:
+ ast_rtp_pt_clear(p->rtp);
+ codecs = m + len;
+ while(strlen(codecs)) {
+ if (sscanf(codecs, "%d%n", &codec, &len) != 1) {
+ ast_log(LOG_WARNING, "Error in codec string '%s'\n", codecs);
+ return -1;
+ }
+ if (sipdebug)
+ ast_verbose("Found audio format %d\n", codec);
+ ast_rtp_set_m_type(p->rtp, codec);
+ codecs += len;
+ /* Skip over any whitespace */
+ while(*codecs && (*codecs < 33)) codecs++;
+ }
+ }
+ if (p->vrtp && (sscanf(m, "video %d RTP/AVP %n", &x, &len) == 1)) {
+ vportno = x;
+ // Scan through the RTP payload types specified in a "m=" line:
+ ast_rtp_pt_clear(p->vrtp);
+ codecs = m + len;
+ while(strlen(codecs)) {
+ if (sscanf(codecs, "%d%n", &codec, &len) != 1) {
+ ast_log(LOG_WARNING, "Error in codec string '%s'\n", codecs);
+ return -1;
+ }
+ if (sipdebug)
+ ast_verbose("Found video format %d\n", codec);
+ ast_rtp_set_m_type(p->vrtp, codec);
+ codecs += len;
+ /* Skip over any whitespace */
+ while(*codecs && (*codecs < 33)) codecs++;
+ }
+ }
}
sin.sin_family = AF_INET;
memcpy(&sin.sin_addr, hp->h_addr, sizeof(sin.sin_addr));
+ /* Setup audio port number */
sin.sin_port = htons(portno);
- if (p->rtp)
+ if (p->rtp && sin.sin_port)
ast_rtp_set_peer(p->rtp, &sin);
+ /* Setup video port number */
+ sin.sin_port = htons(vportno);
+ if (p->vrtp && sin.sin_port)
+ ast_rtp_set_peer(p->vrtp, &sin);
#if 0
printf("Peer RTP is at port %s:%d\n", inet_ntoa(sin.sin_addr), ntohs(sin.sin_port));
#endif
- // Scan through the RTP payload types specified in a "m=" line:
- ast_rtp_pt_clear(p->rtp);
- codecs = m + len;
- while(strlen(codecs)) {
- if (sscanf(codecs, "%d%n", &codec, &len) != 1) {
- ast_log(LOG_WARNING, "Error in codec string '%s'\n", codecs);
- return -1;
- }
- ast_rtp_set_m_type(p->rtp, codec);
- codecs += len;
- /* Skip over any whitespace */
- while(*codecs && (*codecs < 33)) codecs++;
- }
-
// Next, scan through each "a=rtpmap:" line, noting each
// specified RTP payload type (with corresponding MIME subtype):
sdpLineNum_iterator_init(&iterator);
while ((a = get_sdp_iterate(&iterator, req, "a"))[0] != '\0') {
- char* mimeSubtype = strdup(a); // ensures we have enough space
+ char* mimeSubtype = ast_strdupa(a); // ensures we have enough space
+ if (sipdebug)
+ ast_verbose("Pre-Found description format %s\n", mimeSubtype);
if (sscanf(a, "rtpmap: %u %[^/]/", &codec, mimeSubtype) != 2) continue;
+ if (sipdebug)
+ ast_verbose("Found description format %s\n", mimeSubtype);
// Note: should really look at the 'freq' and '#chans' params too
ast_rtp_set_rtpmap_type(p->rtp, codec, "audio", mimeSubtype);
- free(mimeSubtype);
+ if (p->vrtp)
+ ast_rtp_set_rtpmap_type(p->vrtp, codec, "video", mimeSubtype);
}
// Now gather all of the codecs that were asked for:
ast_rtp_get_current_formats(p->rtp,
&peercapability, &peernoncodeccapability);
- p->capability = capability & peercapability;
- p->noncodeccapability = noncodeccapability & peernoncodeccapability;
+ ast_rtp_get_current_formats(p->vrtp,
+ &vpeercapability, &vpeernoncodeccapability);
+ p->capability = capability & (peercapability | vpeercapability);
+ p->noncodeccapability = noncodeccapability & (peernoncodeccapability | vpeernoncodeccapability);
+
if (sipdebug) {
- ast_verbose("Capabilities: us - %d, them - %d, combined - %d\n",
- capability, peercapability, p->capability);
+ ast_verbose("Capabilities: us - %d, them - %d/%d, combined - %d\n",
+ capability, peercapability, vpeercapability, p->capability);
ast_verbose("Non-codec capabilities: us - %d, them - %d, combined - %d\n",
noncodeccapability, peernoncodeccapability,
p->noncodeccapability);
@@ -2114,13 +2198,14 @@ static int add_digit(struct sip_request *req, char digit)
return 0;
}
-static int add_sdp(struct sip_request *resp, struct sip_pvt *p, struct ast_rtp *rtp)
+static int add_sdp(struct sip_request *resp, struct sip_pvt *p, struct ast_rtp *rtp, struct ast_rtp *vrtp)
{
int len;
int codec;
int alreadysent = 0;
char costr[80];
struct sockaddr_in sin;
+ struct sockaddr_in vsin;
struct sip_codec_pref *cur;
char v[256];
char s[256];
@@ -2128,9 +2213,12 @@ static int add_sdp(struct sip_request *resp, struct sip_pvt *p, struct ast_rtp *
char c[256];
char t[256];
char m[256];
+ char m2[256];
char a[1024] = "";
+ char a2[1024] = "";
int x;
struct sockaddr_in dest;
+ struct sockaddr_in vdest;
/* XXX We break with the "recommendation" and send our IP, in order that our
peer doesn't have to gethostbyname() us XXX */
len = 0;
@@ -2139,6 +2227,9 @@ static int add_sdp(struct sip_request *resp, struct sip_pvt *p, struct ast_rtp *
return -1;
}
ast_rtp_get_us(p->rtp, &sin);
+ if (p->vrtp)
+ ast_rtp_get_us(p->vrtp, &vsin);
+
if (p->redirip.sin_addr.s_addr) {
dest.sin_port = p->redirip.sin_port;
dest.sin_addr = p->redirip.sin_addr;
@@ -2148,14 +2239,30 @@ static int add_sdp(struct sip_request *resp, struct sip_pvt *p, struct ast_rtp *
dest.sin_addr = p->ourip;
dest.sin_port = sin.sin_port;
}
+
+ /* Determine video destination */
+ if (p->vrtp) {
+ if (p->vredirip.sin_addr.s_addr) {
+ vdest.sin_port = p->vredirip.sin_port;
+ vdest.sin_addr = p->vredirip.sin_addr;
+ } else if (vrtp) {
+ ast_rtp_get_peer(vrtp, &vdest);
+ } else {
+ vdest.sin_addr = p->ourip;
+ vdest.sin_port = vsin.sin_port;
+ }
+ }
if (sipdebug)
ast_verbose("We're at %s port %d\n", inet_ntoa(p->ourip), ntohs(sin.sin_port));
+ if (sipdebug && p->vrtp)
+ ast_verbose("Video is at %s port %d\n", inet_ntoa(p->ourip), ntohs(vsin.sin_port));
snprintf(v, sizeof(v), "v=0\r\n");
snprintf(o, sizeof(o), "o=root %d %d IN IP4 %s\r\n", getpid(), getpid(), inet_ntoa(dest.sin_addr));
snprintf(s, sizeof(s), "s=session\r\n");
snprintf(c, sizeof(c), "c=IN IP4 %s\r\n", inet_ntoa(dest.sin_addr));
snprintf(t, sizeof(t), "t=0 0\r\n");
snprintf(m, sizeof(m), "m=audio %d RTP/AVP", ntohs(dest.sin_port));
+ snprintf(m2, sizeof(m2), "m=video %d RTP/AVP", ntohs(vdest.sin_port));
/* Start by sending our preferred codecs */
cur = prefs;
while(cur) {
@@ -2165,9 +2272,15 @@ static int add_sdp(struct sip_request *resp, struct sip_pvt *p, struct ast_rtp *
codec = ast_rtp_lookup_code(p->rtp, 1, cur->codec);
if (codec > -1) {
snprintf(costr, sizeof(costr), " %d", codec);
- strcat(m, costr);
- snprintf(costr, sizeof(costr), "a=rtpmap:%d %s/8000\r\n", codec, ast_rtp_lookup_mime_subtype(1, cur->codec));
- strcat(a, costr);
+ if (cur->codec < AST_FORMAT_MAX_AUDIO) {
+ strcat(m, costr);
+ snprintf(costr, sizeof(costr), "a=rtpmap:%d %s/8000\r\n", codec, ast_rtp_lookup_mime_subtype(1, cur->codec));
+ strcat(a, costr);
+ } else {
+ strcat(m2, costr);
+ snprintf(costr, sizeof(costr), "a=rtpmap:%d %s/90000\r\n", codec, ast_rtp_lookup_mime_subtype(1, cur->codec));
+ strcat(a2, costr);
+ }
}
}
alreadysent |= cur->codec;
@@ -2180,10 +2293,16 @@ static int add_sdp(struct sip_request *resp, struct sip_pvt *p, struct ast_rtp *
ast_verbose("Answering with capability %d\n", x);
codec = ast_rtp_lookup_code(p->rtp, 1, x);
if (codec > -1) {
- snprintf(costr, sizeof(costr), " %d", codec);
- strcat(m, costr);
- snprintf(costr, sizeof(costr), "a=rtpmap:%d %s/8000\r\n", codec, ast_rtp_lookup_mime_subtype(1, x));
- strcat(a, costr);
+ snprintf(costr, sizeof(costr), " %d", codec);
+ if (x < AST_FORMAT_MAX_AUDIO) {
+ strcat(m, costr);
+ snprintf(costr, sizeof(costr), "a=rtpmap:%d %s/8000\r\n", codec, ast_rtp_lookup_mime_subtype(1, x));
+ strcat(a, costr);
+ } else {
+ strcat(m2, costr);
+ snprintf(costr, sizeof(costr), "a=rtpmap:%d %s/90000\r\n", codec, ast_rtp_lookup_mime_subtype(1, x));
+ strcat(a2, costr);
+ }
}
}
}
@@ -2207,7 +2326,10 @@ static int add_sdp(struct sip_request *resp, struct sip_pvt *p, struct ast_rtp *
}
}
strcat(m, "\r\n");
+ strcat(m2, "\r\n");
len = strlen(v) + strlen(s) + strlen(o) + strlen(c) + strlen(t) + strlen(m) + strlen(a);
+ if (p->vrtp)
+ len += strlen(m2) + strlen(a2);
snprintf(costr, sizeof(costr), "%d", len);
add_header(resp, "Content-Type", "application/sdp");
add_header(resp, "Content-Length", costr);
@@ -2218,6 +2340,10 @@ static int add_sdp(struct sip_request *resp, struct sip_pvt *p, struct ast_rtp *
add_line(resp, t);
add_line(resp, m);
add_line(resp, a);
+ if (p->vrtp) {
+ add_line(resp, m2);
+ add_line(resp, a2);
+ }
return 0;
}
@@ -2244,7 +2370,7 @@ static int transmit_response_with_sdp(struct sip_pvt *p, char *msg, struct sip_r
return -1;
}
respprep(&resp, p, msg, req);
- add_sdp(&resp, p, NULL);
+ add_sdp(&resp, p, NULL, NULL);
return send_response(p, &resp, retrans, seqno);
}
@@ -2307,14 +2433,14 @@ static int determine_firstline_parts( struct sip_request *req ) {
return 1;
}
-static int transmit_reinvite_with_sdp(struct sip_pvt *p, struct ast_rtp *rtp)
+static int transmit_reinvite_with_sdp(struct sip_pvt *p, struct ast_rtp *rtp, struct ast_rtp *vrtp)
{
struct sip_request req;
if (p->canreinvite == REINVITE_UPDATE)
reqprep(&req, p, "UPDATE", 0);
else
reqprep(&req, p, "INVITE", 0);
- add_sdp(&req, p, rtp);
+ add_sdp(&req, p, rtp, vrtp);
/* Use this as the basis */
copy_request(&p->initreq, &req);
parse(&p->initreq);
@@ -2410,7 +2536,7 @@ static int transmit_invite(struct sip_pvt *p, char *cmd, int sdp, char *auth, ch
add_header(&req, "Alert-info",distinctive_ring);
}
if (sdp) {
- add_sdp(&req, p, NULL);
+ add_sdp(&req, p, NULL, NULL);
} else {
add_header(&req, "Content-Length", "0");
add_blank_header(&req);
@@ -3437,6 +3563,10 @@ static int check_user(struct sip_pvt *p, struct sip_request *req, char *cmd, cha
ast_log(LOG_DEBUG, "Setting NAT on RTP to %d\n", p->nat);
ast_rtp_setnat(p->rtp, p->nat);
}
+ if (p->vrtp) {
+ ast_log(LOG_DEBUG, "Setting NAT on VRTP to %d\n", p->nat);
+ ast_rtp_setnat(p->vrtp, p->nat);
+ }
if (!(res = check_auth(p, req, p->randdata, sizeof(p->randdata), user->name, user->secret, cmd, uri, reliable))) {
sip_cancel_destroy(p);
if (strlen(user->context))
@@ -3475,6 +3605,10 @@ static int check_user(struct sip_pvt *p, struct sip_request *req, char *cmd, cha
ast_log(LOG_DEBUG, "Setting NAT on RTP to %d\n", p->nat);
ast_rtp_setnat(p->rtp, p->nat);
}
+ if (p->vrtp) {
+ ast_log(LOG_DEBUG, "Setting NAT on VRTP to %d\n", p->nat);
+ ast_rtp_setnat(p->vrtp, p->nat);
+ }
p->canreinvite = peer->canreinvite;
strncpy(p->username, peer->name, sizeof(p->username) - 1);
if (strlen(peer->context))
@@ -4124,6 +4258,10 @@ static void handle_response(struct sip_pvt *p, int resp, char *rest, struct sip_
/* Immediately stop RTP */
ast_rtp_stop(p->rtp);
}
+ if (p->vrtp) {
+ /* Immediately stop VRTP */
+ ast_rtp_stop(p->vrtp);
+ }
/* XXX Locking issues?? XXX */
switch(resp) {
case 302: /* Moved temporarily */
@@ -4466,6 +4604,10 @@ static int handle_request(struct sip_pvt *p, struct sip_request *req, struct soc
/* Immediately stop RTP */
ast_rtp_stop(p->rtp);
}
+ if (p->vrtp) {
+ /* Immediately stop VRTP */
+ ast_rtp_stop(p->vrtp);
+ }
if (p->owner)
ast_queue_hangup(p->owner, 0);
transmit_response(p, "200 OK", req);
@@ -4478,6 +4620,10 @@ static int handle_request(struct sip_pvt *p, struct sip_request *req, struct soc
/* Immediately stop RTP */
ast_rtp_stop(p->rtp);
}
+ if (p->vrtp) {
+ /* Immediately stop VRTP */
+ ast_rtp_stop(p->vrtp);
+ }
if (p->owner)
ast_queue_hangup(p->owner, 0);
transmit_response(p, "200 OK", req);
@@ -5238,6 +5384,7 @@ static int reload_config(void)
strcpy(language, "");
strcpy(fromdomain, "");
globalcanreinvite = REINVITE_INVITE;
+ videosupport = 0;
v = ast_variable_browse(cfg, "general");
while(v) {
/* Create the interface list */
@@ -5254,6 +5401,8 @@ static int reload_config(void)
ast_log(LOG_WARNING, "Unknown dtmf mode '%s', using rfc2833\n", v->value);
globaldtmfmode = SIP_DTMF_RFC2833;
}
+ } else if (!strcasecmp(v->name, "videosupport")) {
+ videosupport = ast_true(v->value);
} else if (!strcasecmp(v->name, "notifymimetype")) {
strncpy(notifymime, v->value, sizeof(notifymime) - 1);
} else if (!strcasecmp(v->name, "language")) {
@@ -5422,7 +5571,16 @@ static struct ast_rtp *sip_get_rtp_peer(struct ast_channel *chan)
return NULL;
}
-static int sip_set_rtp_peer(struct ast_channel *chan, struct ast_rtp *rtp)
+static struct ast_rtp *sip_get_vrtp_peer(struct ast_channel *chan)
+{
+ struct sip_pvt *p;
+ p = chan->pvt->pvt;
+ if (p && p->vrtp && p->canreinvite)
+ return p->vrtp;
+ return NULL;
+}
+
+static int sip_set_rtp_peer(struct ast_channel *chan, struct ast_rtp *rtp, struct ast_rtp *vrtp)
{
struct sip_pvt *p;
p = chan->pvt->pvt;
@@ -5431,7 +5589,11 @@ static int sip_set_rtp_peer(struct ast_channel *chan, struct ast_rtp *rtp)
ast_rtp_get_peer(rtp, &p->redirip);
else
memset(&p->redirip, 0, sizeof(p->redirip));
- transmit_reinvite_with_sdp(p, rtp);
+ if (vrtp)
+ ast_rtp_get_peer(vrtp, &p->vredirip);
+ else
+ memset(&p->vredirip, 0, sizeof(p->vredirip));
+ transmit_reinvite_with_sdp(p, rtp, vrtp);
p->outgoing = 1;
return 0;
}
@@ -5440,6 +5602,7 @@ static int sip_set_rtp_peer(struct ast_channel *chan, struct ast_rtp *rtp)
static struct ast_rtp_protocol sip_rtp = {
get_rtp_info: sip_get_rtp_peer,
+ get_vrtp_info: sip_get_vrtp_peer,
set_rtp_peer: sip_set_rtp_peer,
};