mirror of https://github.com/sipwise/asterisk.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
158 lines
6.6 KiB
158 lines
6.6 KiB
Index: channels/chan_sip.c
|
|
===================================================================
|
|
--- channels/chan_sip.c (revision 207422)
|
|
+++ channels/chan_sip.c (revision 207423)
|
|
@@ -911,6 +911,10 @@
|
|
enum referstatus status; /*!< REFER status */
|
|
};
|
|
|
|
+struct offered_media {
|
|
+ int offered;
|
|
+ char text[128];
|
|
+};
|
|
/*! \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 */
|
|
@@ -1034,6 +1038,21 @@
|
|
struct sip_invite_param *options; /*!< Options for INVITE */
|
|
int autoframing;
|
|
int hangupcause; /*!< Storage of hangupcause copied from our owner before we disconnect from the AST channel (only used at hangup) */
|
|
+ /*! When receiving an SDP offer, it is important to take note of what media types were offered.
|
|
+ * By doing this, even if we don't want to answer a particular media stream with something meaningful, we can
|
|
+ * still put an m= line in our answer with the port set to 0.
|
|
+ *
|
|
+ * The reason for the length being 3 is that in this branch of Asterisk, the only media types supported are
|
|
+ * image, audio, and video. Therefore we need to keep track of which types of media were offered.
|
|
+ *
|
|
+ * Note that if we wanted to be 100% correct, we would keep a list of all media streams offered. That way we could respond
|
|
+ * even to unknown media types, and we could respond to multiple streams of the same type. Such large-scale changes
|
|
+ * are not a good idea for released branches, though, so we're compromising by just making sure that for the common cases:
|
|
+ * audio and video, and audio and T.38, we give the appropriate response to both media streams.
|
|
+ *
|
|
+ * The large-scale changes would be a good idea for implementing during an SDP rewrite.
|
|
+ */
|
|
+ struct offered_media offered_media[3];
|
|
} *iflist = NULL;
|
|
|
|
/*! Max entires in the history list for a sip_pvt */
|
|
@@ -5148,6 +5167,7 @@
|
|
enum media_type {
|
|
SDP_AUDIO,
|
|
SDP_VIDEO,
|
|
+ SDP_IMAGE,
|
|
};
|
|
|
|
static int get_ip_and_port_from_sdp(struct sip_request *req, const enum media_type media, struct sockaddr_in *sin)
|
|
@@ -5274,6 +5294,7 @@
|
|
/* Update our last rtprx when we receive an SDP, too */
|
|
p->lastrtprx = p->lastrtptx = time(NULL); /* XXX why both ? */
|
|
|
|
+ memset(p->offered_media, 0, sizeof(p->offered_media));
|
|
|
|
/* Try to find first media stream */
|
|
m = get_sdp(req, "m");
|
|
@@ -5312,11 +5333,14 @@
|
|
if ((sscanf(m, "audio %d/%d RTP/AVP %n", &x, &numberofports, &len) == 2 && len > 0) ||
|
|
(sscanf(m, "audio %d RTP/AVP %n", &x, &len) == 1 && len > 0)) {
|
|
audio = TRUE;
|
|
+ p->offered_media[SDP_AUDIO].offered = TRUE;
|
|
numberofmediastreams++;
|
|
/* Found audio stream in this media definition */
|
|
portno = x;
|
|
/* Scan through the RTP payload types specified in a "m=" line: */
|
|
- for (codecs = m + len; !ast_strlen_zero(codecs); codecs = ast_skip_blanks(codecs + len)) {
|
|
+ codecs = m + len;
|
|
+ ast_copy_string(p->offered_media[SDP_AUDIO].text, codecs, sizeof(p->offered_media[SDP_AUDIO].text));
|
|
+ for (; !ast_strlen_zero(codecs); codecs = ast_skip_blanks(codecs + len)) {
|
|
if (sscanf(codecs, "%d%n", &codec, &len) != 1) {
|
|
ast_log(LOG_WARNING, "Error in codec string '%s'\n", codecs);
|
|
return -1;
|
|
@@ -5328,10 +5352,13 @@
|
|
} else if ((sscanf(m, "video %d/%d RTP/AVP %n", &x, &numberofports, &len) == 2 && len > 0) ||
|
|
(sscanf(m, "video %d RTP/AVP %n", &x, &len) == 1 && len >= 0)) {
|
|
/* If it is not audio - is it video ? */
|
|
- ast_clear_flag(&p->flags[0], SIP_NOVIDEO);
|
|
+ ast_clear_flag(&p->flags[0], SIP_NOVIDEO);
|
|
+ p->offered_media[SDP_VIDEO].offered = TRUE;
|
|
numberofmediastreams++;
|
|
vportno = x;
|
|
/* Scan through the RTP payload types specified in a "m=" line: */
|
|
+ codecs = m + len;
|
|
+ ast_copy_string(p->offered_media[SDP_VIDEO].text, codecs, sizeof(p->offered_media[SDP_VIDEO].text));
|
|
for (codecs = m + len; !ast_strlen_zero(codecs); codecs = ast_skip_blanks(codecs + len)) {
|
|
if (sscanf(codecs, "%d%n", &codec, &len) != 1) {
|
|
ast_log(LOG_WARNING, "Error in codec string '%s'\n", codecs);
|
|
@@ -5345,6 +5372,7 @@
|
|
(sscanf(m, "image %d UDPTL t38%n", &x, &len) == 1 && len >= 0) )) {
|
|
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;
|
|
numberofmediastreams++;
|
|
|
|
@@ -6670,6 +6698,7 @@
|
|
size_t a_audio_left = sizeof(a_audio);
|
|
size_t a_video_left = sizeof(a_video);
|
|
size_t a_modem_left = sizeof(a_modem);
|
|
+ char dummy_answer[256];
|
|
|
|
int x;
|
|
int capability = 0;
|
|
@@ -6756,7 +6785,7 @@
|
|
vdest.sin_addr = p->ourip;
|
|
vdest.sin_port = vsin.sin_port;
|
|
}
|
|
- ast_build_string(&m_video_next, &m_video_left, "m=video %d RTP/AVP", ntohs(vdest.sin_port));
|
|
+ ast_build_string(&m_video_next, &m_video_left, "m=video %d RTP/AVP", ntohs(vsin.sin_port));
|
|
|
|
/* Build max bitrate string */
|
|
if (p->maxcallbitrate)
|
|
@@ -6926,15 +6955,23 @@
|
|
add_line(resp, m_audio);
|
|
add_line(resp, a_audio);
|
|
add_line(resp, hold);
|
|
+ } else if (p->offered_media[SDP_AUDIO].offered) {
|
|
+ snprintf(dummy_answer, sizeof(dummy_answer), "m=audio 0 RTP/AVP %s\r\n", p->offered_media[SDP_AUDIO].text);
|
|
+ add_line(resp, dummy_answer);
|
|
}
|
|
if (needvideo) { /* only if video response is appropriate */
|
|
add_line(resp, m_video);
|
|
add_line(resp, a_video);
|
|
add_line(resp, hold); /* Repeat hold for the video stream */
|
|
+ } else if (p->offered_media[SDP_VIDEO].offered) {
|
|
+ snprintf(dummy_answer, sizeof(dummy_answer), "m=video 0 RTP/AVP %s\r\n", p->offered_media[SDP_VIDEO].text);
|
|
+ add_line(resp, dummy_answer);
|
|
}
|
|
if (add_t38) {
|
|
add_line(resp, m_modem);
|
|
add_line(resp, a_modem);
|
|
+ } else if (p->offered_media[SDP_IMAGE].offered) {
|
|
+ add_line(resp, "m=image 0 udptl t38\r\n");
|
|
}
|
|
|
|
/* Update lastrtprx when we send our SDP */
|
|
@@ -7076,6 +7113,7 @@
|
|
add_header(&req, "X-asterisk-Info", "SIP re-invite (External RTP bridge)");
|
|
if (!ast_test_flag(&p->flags[0], SIP_NO_HISTORY))
|
|
append_history(p, "ReInv", "Re-invite sent");
|
|
+ memset(p->offered_media, 0, sizeof(p->offered_media));
|
|
add_sdp(&req, p, 1, 0);
|
|
/* Use this as the basis */
|
|
initialize_initreq(p, &req);
|
|
@@ -7098,6 +7136,7 @@
|
|
add_header(&req, "Supported", SUPPORTED_EXTENSIONS);
|
|
if (sipdebug)
|
|
add_header(&req, "X-asterisk-info", "SIP re-invite (T38 switchover)");
|
|
+ memset(p->offered_media, 0, sizeof(p->offered_media));
|
|
add_sdp(&req, p, 0, 1);
|
|
|
|
/* Use this as the basis */
|
|
@@ -7430,6 +7469,7 @@
|
|
ast_channel_unlock(chan);
|
|
}
|
|
if (sdp) {
|
|
+ memset(p->offered_media, 0, sizeof(p->offered_media));
|
|
if (p->udptl && p->t38.state == T38_LOCAL_REINVITE) {
|
|
ast_udptl_offered_from_local(p->udptl, 1);
|
|
if (option_debug)
|