[asterisk-commits] kpfleming: branch kpfleming/sdp-parsing-unbreakage r229636 - in /team/kpflemi...
SVN commits to the Asterisk project
asterisk-commits at lists.digium.com
Thu Nov 12 06:53:20 CST 2009
Author: kpfleming
Date: Thu Nov 12 06:53:16 2009
New Revision: 229636
URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=229636
Log:
save away some work in progress to restore the ability to actually use T.38 sessions with the new SDP parser
Added:
team/kpfleming/sdp-parsing-unbreakage/
- copied from r229607, branches/1.6.0/
Modified:
team/kpfleming/sdp-parsing-unbreakage/channels/chan_sip.c
Modified: team/kpfleming/sdp-parsing-unbreakage/channels/chan_sip.c
URL: http://svnview.digium.com/svn/asterisk/team/kpfleming/sdp-parsing-unbreakage/channels/chan_sip.c?view=diff&rev=229636&r1=229607&r2=229636
==============================================================================
--- team/kpfleming/sdp-parsing-unbreakage/channels/chan_sip.c (original)
+++ team/kpfleming/sdp-parsing-unbreakage/channels/chan_sip.c Thu Nov 12 06:53:16 2009
@@ -6891,20 +6891,18 @@
struct ast_hostent audiohp;
struct ast_hostent videohp;
struct ast_hostent texthp;
- struct hostent *hp = NULL; /*!< RTP Audio host IP */
- struct hostent *vhp = NULL; /*!< RTP video host IP */
- struct hostent *thp = NULL; /*!< RTP text host IP */
- int portno = -1; /*!< RTP Audio port number */
+ struct ast_hostent imagehp;
+ struct hostent *ahp = NULL; /*!< RTP Audio host IP */
+ struct hostent *vhp = NULL; /*!< RTP Video host IP */
+ struct hostent *thp = NULL; /*!< RTP Text host IP */
+ struct hostent *ihp = NULL; /*!< UDPTL image host IP */
+ int aportno = -1; /*!< RTP Audio port number */
int vportno = -1; /*!< RTP Video port number */
int tportno = -1; /*!< RTP Text port number */
- int udptlportno = -1; /*!< UDPTL Image port number */
- struct sockaddr_in sin; /*!< media socket address */
- struct sockaddr_in vsin; /*!< video socket address */
- struct sockaddr_in isin; /*!< image socket address */
- struct sockaddr_in tsin; /*!< text socket address */
+ int iportno = -1; /*!< UDPTL Image port number */
/* Peer capability is the capability in the SDP, non codec is RFC2833 DTMF (101) */
- int peercapability = 0, peernoncodeccapability = 0;
+ int apeercapability = 0, apeernoncodeccapability = 0;
int vpeercapability = 0, vpeernoncodeccapability = 0;
int tpeercapability = 0, tpeernoncodeccapability = 0;
@@ -6967,17 +6965,10 @@
memset(p->offered_media, 0, sizeof(p->offered_media));
-
/* default: novideo and notext set */
p->novideo = TRUE;
p->notext = TRUE;
- if (p->vrtp)
- ast_rtp_pt_clear(newvideortp); /* Must be cleared in case no m=video line exists */
-
- if (p->trtp)
- ast_rtp_pt_clear(newtextrtp); /* Must be cleared in case no m=text line exists */
-
/* Scan for the first media stream (m=) line to limit scanning of globals */
nextm = get_sdp_iterate(&next, req, "m");
if (ast_strlen_zero(nextm)) {
@@ -6990,38 +6981,36 @@
int processed = FALSE;
switch (type) {
case 'o':
- if (!process_sdp_o(value, p))
+ if (!process_sdp_o(value, p)) {
return -1;
+ }
break;
case 'c':
if (process_sdp_c(value, &sessionhp)) {
processed = TRUE;
- hp = &sessionhp.hp;
- vhp = hp;
- thp = hp;
+ ahp = vhp = thp = ihp = &sessionhp.hp;
}
break;
case 'a':
if (process_sdp_a_sendonly(value, &sendonly)) {
processed = TRUE;
vsendonly = sendonly;
+ } else if (process_sdp_a_audio(value, p, newaudiortp, &last_rtpmap_codec)) {
+ processed = TRUE;
+ } else if (process_sdp_a_video(value, p, newvideortp, &last_rtpmap_codec)) {
+ processed = TRUE;
+ } else if (process_sdp_a_text(value, p, newtextrtp, &last_rtpmap_codec)) {
+ processed = TRUE;
+ } else if (process_sdp_a_image(value, p)) {
+ processed = TRUE;
}
- else if (process_sdp_a_audio(value, p, newaudiortp, &last_rtpmap_codec))
- processed = TRUE;
- else if (process_sdp_a_video(value, p, newvideortp, &last_rtpmap_codec))
- processed = TRUE;
- else if (process_sdp_a_text(value, p, newtextrtp, &last_rtpmap_codec))
- processed = TRUE;
- else if (process_sdp_a_image(value, p))
- processed = TRUE;
break;
}
- if (option_debug > 2)
+ if (option_debug > 2) {
ast_log(LOG_DEBUG, "Processing session-level SDP %c=%s... %s\n", type, value, (processed == TRUE)? "OK." : "UNSUPPORTED.");
+ }
}
-
-
/* Scan media stream (m=) specific parameters loop */
while (!ast_strlen_zero(nextm)) {
@@ -7038,13 +7027,12 @@
iterator = next;
nextm = get_sdp_iterate(&next, req, "m");
- /* Search for audio media definition */
if ((sscanf(m, "audio %30d/%30d RTP/AVP %n", &x, &numberofports, &len) == 2 && len > 0) ||
(sscanf(m, "audio %30d RTP/AVP %n", &x, &len) == 1 && len > 0)) {
audio = TRUE;
p->offered_media[SDP_AUDIO].offered = TRUE;
numberofmediastreams++;
- portno = x;
+ aportno = x;
/* Scan through the RTP payload types specified in a "m=" line: */
codecs = m + len;
@@ -7054,12 +7042,11 @@
ast_log(LOG_WARNING, "Error in codec string '%s'\n", codecs);
return -1;
}
- if (debug)
+ if (debug) {
ast_verbose("Found RTP audio format %d\n", codec);
-
+ }
ast_rtp_set_m_type(newaudiortp, codec);
}
- /* Search for video media definition */
} else if ((sscanf(m, "video %30d/%30d RTP/AVP %n", &x, &numberofports, &len) == 2 && len > 0) ||
(sscanf(m, "video %30d RTP/AVP %n", &x, &len) == 1 && len >= 0)) {
video = TRUE;
@@ -7076,11 +7063,11 @@
ast_log(LOG_WARNING, "Error in codec string '%s'\n", codecs);
return -1;
}
- if (debug)
+ if (debug) {
ast_verbose("Found RTP video format %d\n", codec);
+ }
ast_rtp_set_m_type(newvideortp, codec);
}
- /* Search for text media definition */
} else if ((sscanf(m, "text %30d/%30d RTP/AVP %n", &x, &numberofports, &len) == 2 && len > 0) ||
(sscanf(m, "text %30d RTP/AVP %n", &x, &len) == 1 && len > 0)) {
text = TRUE;
@@ -7097,23 +7084,27 @@
ast_log(LOG_WARNING, "Error in codec string '%s'\n", codecs);
return -1;
}
- if (debug)
+ if (debug) {
ast_verbose("Found RTP text format %d\n", codec);
+ }
ast_rtp_set_m_type(newtextrtp, codec);
}
- /* Search for image media definition */
} else if (p->udptl && ((sscanf(m, "image %30d udptl t38%n", &x, &len) == 1 && len > 0) ||
(sscanf(m, "image %30d UDPTL t38%n", &x, &len) == 1 && len > 0) )) {
image = TRUE;
- if (debug)
+ if (debug) {
ast_verbose("Got T.38 offer in SDP in dialog %s\n", p->callid);
+ }
p->offered_media[SDP_IMAGE].offered = TRUE;
- udptlportno = x;
+ iportno = x;
numberofmediastreams++;
if (p->t38.state != T38_ENABLED) {
memset(&p->t38.their_parms, 0, sizeof(p->t38.their_parms));
+ /* KPF: these state changes should not occur until we decide whether
+ we are actually going to accept this offer or not
+ */
/* Remote party offers T38, we need to update state */
if ((t38action == SDP_T38_ACCEPT) &&
(p->t38.state == T38_LOCAL_REINVITE)) {
@@ -7129,10 +7120,9 @@
}
/* Check for number of ports */
- if (numberofports > 1)
+ if (numberofports > 1) {
ast_log(LOG_WARNING, "SDP offered %d ports for media, not supported by Asterisk. Will try anyway...\n", numberofports);
-
-
+ }
/* Media stream specific parameters */
while ((type = get_sdp_line(&iterator, next - 1, req, &value)) != '\0') {
@@ -7143,7 +7133,7 @@
if (audio) {
if (process_sdp_c(value, &audiohp)) {
processed = TRUE;
- hp = &audiohp.hp;
+ ahp = &audiohp.hp;
}
} else if (video) {
if (process_sdp_c(value, &videohp)) {
@@ -7155,73 +7145,71 @@
processed = TRUE;
thp = &texthp.hp;
}
+ } else if (image) {
+ if (process_sdp_c(value, &imagehp)) {
+ processed = TRUE;
+ ihp = &imagehp.hp;
+ }
}
break;
case 'a':
- /* Audio specific scanning */
if (audio) {
- if (process_sdp_a_sendonly(value, &sendonly))
+ if (process_sdp_a_sendonly(value, &sendonly)) {
processed = TRUE;
- else if (process_sdp_a_audio(value, p, newaudiortp, &last_rtpmap_codec))
+ } else if (process_sdp_a_audio(value, p, newaudiortp, &last_rtpmap_codec)) {
processed = TRUE;
- }
- /* Video specific scanning */
- else if (video) {
- if (process_sdp_a_sendonly(value, &vsendonly))
+ }
+ } else if (video) {
+ if (process_sdp_a_sendonly(value, &vsendonly)) {
processed = TRUE;
- else if (process_sdp_a_video(value, p, newvideortp, &last_rtpmap_codec))
+ } else if (process_sdp_a_video(value, p, newvideortp, &last_rtpmap_codec)) {
processed = TRUE;
- }
- /* Text (T.140) specific scanning */
- else if (text) {
- if (process_sdp_a_text(value, p, newtextrtp, &last_rtpmap_codec))
+ }
+ } else if (text) {
+ if (process_sdp_a_text(value, p, newtextrtp, &last_rtpmap_codec)) {
processed = TRUE;
- }
- /* Image (T.38 FAX) specific scanning */
- else if (image) {
- if (process_sdp_a_image(value, p))
+ }
+ } else if (image) {
+ if (process_sdp_a_image(value, p)) {
processed = TRUE;
+ }
}
break;
}
- if (option_debug > 2)
+ if (option_debug > 2) {
ast_log(LOG_DEBUG, "Processing media-level (%s) SDP %c=%s... %s\n",
- (audio == TRUE)? "audio" : (video == TRUE)? "video" : "image",
- type, value,
- (processed == TRUE)? "OK." : "UNSUPPORTED.");
- }
- }
-
+ (audio == TRUE) ? "audio" : (video == TRUE) ? "video" : (image == TRUE) ? "image" : "text",
+ type, value,
+ (processed == TRUE)? "OK." : "UNSUPPORTED.");
+ }
+ }
+ }
/* Sanity checks */
- if (!hp) {
- ast_log(LOG_WARNING, "Insufficient information in SDP (c=)...\n");
- return -1;
- }
-
- if (portno == -1 && vportno == -1 && udptlportno == -1 && tportno == -1)
+ if (aportno == -1 && vportno == -1 && iportno == -1 && tportno == -1) {
/* No acceptable offer found in SDP - we have no ports */
/* Do not change RTP or VRTP if this is a re-invite */
return -2;
-
- if (numberofmediastreams > 3)
+ }
+
+ if (numberofmediastreams > 3) {
/* We have too many fax, audio and/or video and/or text media streams, fail this offer */
return -3;
-
- if (udptlportno == -1) {
+ }
+
+ if (iportno == -1) {
change_t38_state(p, T38_DISABLED);
}
/* Now gather all of the codecs that we are asked for: */
- ast_rtp_get_current_formats(newaudiortp, &peercapability, &peernoncodeccapability);
+ ast_rtp_get_current_formats(newaudiortp, &apeercapability, &apeernoncodeccapability);
ast_rtp_get_current_formats(newvideortp, &vpeercapability, &vpeernoncodeccapability);
ast_rtp_get_current_formats(newtextrtp, &tpeercapability, &tpeernoncodeccapability);
- newjointcapability = p->capability & (peercapability | vpeercapability | tpeercapability);
- newpeercapability = (peercapability | vpeercapability | tpeercapability);
- newnoncodeccapability = p->noncodeccapability & peernoncodeccapability;
-
+ newjointcapability = p->capability & (apeercapability | vpeercapability | tpeercapability);
+ newpeercapability = (apeercapability | vpeercapability | tpeercapability);
+ newnoncodeccapability = p->noncodeccapability & apeernoncodeccapability;
if (debug) {
/* shame on whoever coded this.... */
@@ -7229,24 +7217,25 @@
ast_verbose("Capabilities: us - %s, peer - audio=%s/video=%s/text=%s, combined - %s\n",
ast_getformatname_multiple(s1, SIPBUFSIZE, p->capability),
- ast_getformatname_multiple(s2, SIPBUFSIZE, peercapability),
+ ast_getformatname_multiple(s2, SIPBUFSIZE, apeercapability),
ast_getformatname_multiple(s3, SIPBUFSIZE, vpeercapability),
ast_getformatname_multiple(s4, SIPBUFSIZE, tpeercapability),
ast_getformatname_multiple(s5, SIPBUFSIZE, newjointcapability));
ast_verbose("Non-codec capabilities (dtmf): us - %s, peer - %s, combined - %s\n",
ast_rtp_lookup_mime_multiple(s1, SIPBUFSIZE, p->noncodeccapability, 0, 0),
- ast_rtp_lookup_mime_multiple(s2, SIPBUFSIZE, peernoncodeccapability, 0, 0),
+ ast_rtp_lookup_mime_multiple(s2, SIPBUFSIZE, apeernoncodeccapability, 0, 0),
ast_rtp_lookup_mime_multiple(s3, SIPBUFSIZE, newnoncodeccapability, 0, 0));
}
if (!newjointcapability) {
/* If T.38 was not negotiated either, totally bail out... */
- if ((p->t38.state == T38_DISABLED) || !udptlportno) {
+ if ((p->t38.state == T38_DISABLED) || !iportno) {
ast_log(LOG_NOTICE, "No compatible codecs, not accepting this offer!\n");
/* Do NOT Change current setting */
return -1;
} else {
ast_debug(3, "Have T.38 but no audio codecs, accepting offer anyway\n");
+ /* KPF: except we don't actually finish processing the offer, so the call is broken */
return 0;
}
}
@@ -7278,84 +7267,99 @@
/* Setup audio address and port */
if (p->rtp) {
- if (portno > 0) {
+ if (aportno > 0) {
+ struct sockaddr_in sin;
+
sin.sin_family = AF_INET;
- sin.sin_port = htons(portno);
- memcpy(&sin.sin_addr, hp->h_addr, sizeof(sin.sin_addr));
+ sin.sin_port = htons(aportno);
+ memcpy(&sin.sin_addr, ahp->h_addr, sizeof(sin.sin_addr));
ast_rtp_set_peer(p->rtp, &sin);
- if (debug)
+ if (debug) {
ast_verbose("Peer audio RTP is at port %s:%d\n", ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port));
- } else if (udptlportno > 0) {
- if (debug)
- ast_verbose("Got T.38 Re-invite without audio. Keeping RTP active during T.38 session.\n");
+ }
} else {
ast_rtp_stop(p->rtp);
- if (debug)
- ast_verbose("Peer doesn't provide audio\n");
+ if (debug) {
+ ast_verbose("Peer doesn't want audio\n");
+ }
}
}
/* Setup video address and port */
if (p->vrtp) {
if (vportno > 0) {
- vsin.sin_family = AF_INET;
- vsin.sin_port = htons(vportno);
- memcpy(&vsin.sin_addr, vhp->h_addr, sizeof(vsin.sin_addr));
- ast_rtp_set_peer(p->vrtp, &vsin);
- if (debug)
- ast_verbose("Peer video RTP is at port %s:%d\n", ast_inet_ntoa(vsin.sin_addr), ntohs(vsin.sin_port));
+ struct sockaddr_in sin;
+
+ sin.sin_family = AF_INET;
+ sin.sin_port = htons(vportno);
+ memcpy(&sin.sin_addr, vhp->h_addr, sizeof(sin.sin_addr));
+ ast_rtp_set_peer(p->vrtp, &sin);
+ if (debug) {
+ ast_verbose("Peer video RTP is at port %s:%d\n", ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port));
+ }
} else {
ast_rtp_stop(p->vrtp);
- if (debug)
- ast_verbose("Peer doesn't provide video\n");
+ if (debug) {
+ ast_verbose("Peer doesn't want video\n");
+ }
}
}
/* Setup text address and port */
if (p->trtp) {
if (tportno > 0) {
- tsin.sin_family = AF_INET;
- tsin.sin_port = htons(tportno);
- memcpy(&tsin.sin_addr, thp->h_addr, sizeof(tsin.sin_addr));
- ast_rtp_set_peer(p->trtp, &tsin);
- if (debug)
- ast_verbose("Peer T.140 RTP is at port %s:%d\n", ast_inet_ntoa(vsin.sin_addr), ntohs(vsin.sin_port));
+ struct sockaddr_in sin;
+
+ sin.sin_family = AF_INET;
+ sin.sin_port = htons(tportno);
+ memcpy(&sin.sin_addr, thp->h_addr, sizeof(sin.sin_addr));
+ ast_rtp_set_peer(p->trtp, &sin);
+ if (debug) {
+ ast_verbose("Peer T.140 RTP is at port %s:%d\n", ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port));
+ }
} else {
ast_rtp_stop(p->trtp);
- if (debug)
- ast_verbose("Peer doesn't provide T.140\n");
+ if (debug) {
+ ast_verbose("Peer doesn't want T.140\n");
+ }
}
}
/* Setup image address and port */
if (p->udptl) {
- if (udptlportno > 0) {
- isin.sin_family = AF_INET;
- isin.sin_port = htons(udptlportno);
+ if (iportno > 0) {
+ struct sockaddr_in sin;
+
+ sin.sin_family = AF_INET;
+ sin.sin_port = htons(iportno);
if (ast_test_flag(&p->flags[0], SIP_NAT) && ast_test_flag(&p->flags[1], SIP_PAGE2_UDPTL_DESTINATION)) {
struct sockaddr_in remote_address = { 0, };
ast_rtp_get_peer(p->rtp, &remote_address);
if (remote_address.sin_addr.s_addr) {
- memcpy(&isin, &remote_address, sizeof(isin));
+ memcpy(&sin, &remote_address, sizeof(sin));
if (debug) {
- ast_log(LOG_DEBUG, "Peer T.38 UDPTL is set behind NAT and with destination, destination address now %s\n", ast_inet_ntoa(isin.sin_addr));
+ ast_log(LOG_DEBUG, "Peer T.38 UDPTL is set behind NAT and with destination, destination address now %s\n", ast_inet_ntoa(sin.sin_addr));
}
}
}
- ast_udptl_set_peer(p->udptl, &isin);
- if (debug)
- ast_debug(1,"Peer T.38 UDPTL is at port %s:%d\n", ast_inet_ntoa(isin.sin_addr), ntohs(isin.sin_port));
+ ast_udptl_set_peer(p->udptl, &sin);
+ if (debug) {
+ ast_debug(1,"Peer T.38 UDPTL is at port %s:%d\n", ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port));
+ }
} else {
ast_udptl_stop(p->udptl);
- if (debug)
- ast_debug(1, "Peer doesn't provide T.38 UDPTL\n");
+ if (debug) {
+ ast_debug(1, "Peer doesn't want T.38 UDPTL\n");
+ }
}
}
/* Ok, we're going with this offer */
ast_debug(2, "We're settling with these formats: %s\n", ast_getformatname_multiple(buf, SIPBUFSIZE, p->jointcapability));
- if (!p->owner) /* There's no open channel owning us so we can return here. For a re-invite or so, we proceed */
+ if (!p->owner) {
+ /* There's no open channel owning us so we can return here. For a re-invite or so, we proceed */
return 0;
+ }
ast_debug(4, "We have an owner, now see if we need to change this call\n");
@@ -7363,37 +7367,41 @@
if (debug) {
char s1[SIPBUFSIZE], s2[SIPBUFSIZE];
ast_debug(1, "Oooh, we need to change our audio formats since our peer supports only %s and not %s\n",
- ast_getformatname_multiple(s1, SIPBUFSIZE, p->jointcapability),
- ast_getformatname_multiple(s2, SIPBUFSIZE, p->owner->nativeformats));
+ ast_getformatname_multiple(s1, SIPBUFSIZE, p->jointcapability),
+ ast_getformatname_multiple(s2, SIPBUFSIZE, p->owner->nativeformats));
}
p->owner->nativeformats = ast_codec_choose(&p->prefs, p->jointcapability, 1) | (p->capability & vpeercapability) | (p->capability & tpeercapability);
ast_set_read_format(p->owner, p->owner->readformat);
ast_set_write_format(p->owner, p->owner->writeformat);
}
- if (ast_test_flag(&p->flags[1], SIP_PAGE2_CALL_ONHOLD) && sin.sin_addr.s_addr && (!sendonly || sendonly == -1)) {
+ if (ast_test_flag(&p->flags[1], SIP_PAGE2_CALL_ONHOLD) && ahp && ahp->h_addr && (!sendonly || sendonly == -1)) {
ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
/* Activate a re-invite */
ast_queue_frame(p->owner, &ast_null_frame);
/* Queue Manager Unhold event */
append_history(p, "Unhold", "%s", req->data);
- if (global_callevents)
+ if (global_callevents) {
manager_event(EVENT_FLAG_CALL, "Hold",
"Status: Off\r\n"
"Channel: %s\r\n"
"Uniqueid: %s\r\n",
p->owner->name,
p->owner->uniqueid);
- if (global_notifyhold)
+ }
+ if (global_notifyhold) {
sip_peer_hold(p, FALSE);
+ }
ast_clear_flag(&p->flags[1], SIP_PAGE2_CALL_ONHOLD); /* Clear both flags */
- } else if (!sin.sin_addr.s_addr || (sendonly && sendonly != -1)) {
+ } else if ((ahp && !ahp->h_addr) || (sendonly && sendonly != -1)) {
int already_on_hold = ast_test_flag(&p->flags[1], SIP_PAGE2_CALL_ONHOLD);
+
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)
+ 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);
@@ -7407,14 +7415,18 @@
p->owner->name,
p->owner->uniqueid);
}
- if (sendonly == 1) /* One directional hold (sendonly/recvonly) */
+ if (sendonly == 1) {
+ /* One directional hold (sendonly/recvonly) */
ast_set_flag(&p->flags[1], SIP_PAGE2_CALL_ONHOLD_ONEDIR);
- else if (sendonly == 2) /* Inactive stream */
+ } else if (sendonly == 2) {
+ /* Inactive stream */
ast_set_flag(&p->flags[1], SIP_PAGE2_CALL_ONHOLD_INACTIVE);
- else
+ } else {
ast_set_flag(&p->flags[1], SIP_PAGE2_CALL_ONHOLD_ACTIVE);
- if (global_notifyhold && !already_on_hold)
+ }
+ if (global_notifyhold && !already_on_hold) {
sip_peer_hold(p, TRUE);
+ }
}
return 0;
More information about the asterisk-commits
mailing list