diff --git a/channels/chan_sip.c b/channels/chan_sip.c index 4103fa52fc53845c0960b9d72d7718ab518af729..fd858649e608416365163930db738df368b5030a 100644 --- a/channels/chan_sip.c +++ b/channels/chan_sip.c @@ -8374,9 +8374,11 @@ static int process_sdp(struct sip_pvt *p, struct sip_request *req, int t38action struct ast_hostent audiohp; struct ast_hostent videohp; struct ast_hostent texthp; + struct ast_hostent imagehp; struct hostent *hp = 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 host ip */ int portno = -1; /*!< RTP Audio port number */ int vportno = -1; /*!< RTP Video port number */ int tportno = -1; /*!< RTP Text port number */ @@ -8463,6 +8465,7 @@ static int process_sdp(struct sip_pvt *p, struct sip_request *req, int t38action hp = &sessionhp.hp; vhp = hp; thp = hp; + ihp = hp; } break; case 'a': @@ -8577,15 +8580,6 @@ static int process_sdp(struct sip_pvt *p, struct sip_request *req, int t38action if (p->t38.state != T38_ENABLED) { memset(&p->t38.their_parms, 0, sizeof(p->t38.their_parms)); - - /* Remote party offers T38, we need to update state */ - if ((t38action == SDP_T38_ACCEPT) && - (p->t38.state == T38_LOCAL_REINVITE)) { - change_t38_state(p, T38_ENABLED); - } else if ((t38action == SDP_T38_INITIATE) && - p->owner && p->lastinvite) { - change_t38_state(p, T38_PEER_REINVITE); /* T38 Offered in re-invite from remote party */ - } } } else { ast_log(LOG_WARNING, "Unsupported SDP media type in offer: %s\n", m); @@ -8619,6 +8613,11 @@ static int process_sdp(struct sip_pvt *p, struct sip_request *req, int t38action processed = TRUE; thp = &texthp.hp; } + } else if (image) { + if (process_sdp_c(value, &imagehp)) { + processed = TRUE; + ihp = &imagehp.hp; + } } break; case 'a': @@ -8708,54 +8707,10 @@ static int process_sdp(struct sip_pvt *p, struct sip_request *req, int t38action ast_rtp_lookup_mime_multiple2(s2, peernoncodeccapability, 0, 0), ast_rtp_lookup_mime_multiple2(s3, newnoncodeccapability, 0, 0)); } - if (!newjointcapability) { - /* If T.38 was not negotiated either, totally bail out... */ - if ((p->t38.state == T38_DISABLED) || !udptlportno) { - 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"); - return 0; - } - } - - /* We are now ready to change the sip session and p->rtp and p->vrtp with the offered codecs, since - they are acceptable */ - p->jointcapability = newjointcapability; /* Our joint codec profile for this call */ - p->peercapability = newpeercapability; /* The other sides capability in latest offer */ - p->jointnoncodeccapability = newnoncodeccapability; /* DTMF capabilities */ - - if (ast_test_flag(&p->flags[1], SIP_PAGE2_PREFERRED_CODEC)) { /* respond with single most preferred joint codec, limiting the other side's choice */ - p->jointcapability = ast_codec_choose(&p->prefs, p->jointcapability, 1); - } - - if (p->trtp && (p->jointcapability & AST_FORMAT_T140RED)) { - p->red = 1; - ast_rtp_red_init(p->trtp, 300, red_data_pt, 2); - } else { - p->red = 0; - } - - ast_rtp_codecs_payloads_copy(&newaudiortp, ast_rtp_instance_get_codecs(p->rtp), p->rtp); - if (p->vrtp) { - ast_rtp_codecs_payloads_copy(&newvideortp, ast_rtp_instance_get_codecs(p->vrtp), p->vrtp); - } - if (p->trtp) { - ast_rtp_codecs_payloads_copy(&newtextrtp, ast_rtp_instance_get_codecs(p->trtp), p->trtp); - } - - if (ast_test_flag(&p->flags[0], SIP_DTMF) == SIP_DTMF_AUTO) { - ast_clear_flag(&p->flags[0], SIP_DTMF); - if (newnoncodeccapability & AST_RTP_DTMF) { - /* XXX Would it be reasonable to drop the DSP at this point? XXX */ - ast_set_flag(&p->flags[0], SIP_DTMF_RFC2833); - /* Since RFC2833 is now negotiated we need to change some properties of the RTP stream */ - ast_rtp_instance_set_prop(p->rtp, AST_RTP_PROPERTY_DTMF, 1); - ast_rtp_instance_set_prop(p->rtp, AST_RTP_PROPERTY_DTMF_COMPENSATE, ast_test_flag(&p->flags[1], SIP_PAGE2_RFC2833_COMPENSATE)); - } else { - ast_set_flag(&p->flags[0], SIP_DTMF_INBAND); - } + if (!newjointcapability && (portno != -1)) { + ast_log(LOG_NOTICE, "No compatible codecs, not accepting this offer!\n"); + /* Do NOT Change current setting */ + return -1; } /* Setup audio address and port */ @@ -8767,6 +8722,30 @@ static int process_sdp(struct sip_pvt *p, struct sip_request *req, int t38action ast_rtp_instance_set_remote_address(p->rtp, &sin); if (debug) ast_verbose("Peer audio RTP is at port %s:%d\n", ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port)); + /* We are now ready to change the sip session and p->rtp and p->vrtp with the offered codecs, since + they are acceptable */ + p->jointcapability = newjointcapability; /* Our joint codec profile for this call */ + p->peercapability = newpeercapability; /* The other sides capability in latest offer */ + p->jointnoncodeccapability = newnoncodeccapability; /* DTMF capabilities */ + + if (ast_test_flag(&p->flags[1], SIP_PAGE2_PREFERRED_CODEC)) { /* respond with single most preferred joint codec, limiting the other side's choice */ + p->jointcapability = ast_codec_choose(&p->prefs, p->jointcapability, 1); + } + + ast_rtp_codecs_payloads_copy(&newaudiortp, ast_rtp_instance_get_codecs(p->rtp), p->rtp); + + if (ast_test_flag(&p->flags[0], SIP_DTMF) == SIP_DTMF_AUTO) { + ast_clear_flag(&p->flags[0], SIP_DTMF); + if (newnoncodeccapability & AST_RTP_DTMF) { + /* XXX Would it be reasonable to drop the DSP at this point? XXX */ + ast_set_flag(&p->flags[0], SIP_DTMF_RFC2833); + /* Since RFC2833 is now negotiated we need to change some properties of the RTP stream */ + ast_rtp_instance_set_prop(p->rtp, AST_RTP_PROPERTY_DTMF, 1); + ast_rtp_instance_set_prop(p->rtp, AST_RTP_PROPERTY_DTMF_COMPENSATE, ast_test_flag(&p->flags[1], SIP_PAGE2_RFC2833_COMPENSATE)); + } else { + ast_set_flag(&p->flags[0], SIP_DTMF_INBAND); + } + } } else if (udptlportno > 0) { if (debug) ast_verbose("Got T.38 Re-invite without audio. Keeping RTP active during T.38 session.\n"); @@ -8786,6 +8765,7 @@ static int process_sdp(struct sip_pvt *p, struct sip_request *req, int t38action ast_rtp_instance_set_remote_address(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)); + ast_rtp_codecs_payloads_copy(&newvideortp, ast_rtp_instance_get_codecs(p->vrtp), p->vrtp); } else { ast_rtp_instance_stop(p->vrtp); if (debug) @@ -8802,6 +8782,13 @@ static int process_sdp(struct sip_pvt *p, struct sip_request *req, int t38action ast_rtp_instance_set_remote_address(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)); + if ((p->jointcapability & AST_FORMAT_T140RED)) { + p->red = 1; + ast_rtp_red_init(p->trtp, 300, red_data_pt, 2); + } else { + p->red = 0; + } + ast_rtp_codecs_payloads_copy(&newtextrtp, ast_rtp_instance_get_codecs(p->trtp), p->trtp); } else { ast_rtp_instance_stop(p->trtp); if (debug) @@ -8822,10 +8809,21 @@ static int process_sdp(struct sip_pvt *p, struct sip_request *req, int t38action 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)); } } + } else { + memcpy(&isin.sin_addr, ihp->h_addr, sizeof(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)); + + /* Remote party offers T38, we need to update state */ + if ((t38action == SDP_T38_ACCEPT) && + (p->t38.state == T38_LOCAL_REINVITE)) { + change_t38_state(p, T38_ENABLED); + } else if ((t38action == SDP_T38_INITIATE) && + p->owner && p->lastinvite) { + change_t38_state(p, T38_PEER_REINVITE); /* T38 Offered in re-invite from remote party */ + } } else { ast_udptl_stop(p->udptl); if (debug) @@ -8833,6 +8831,11 @@ static int process_sdp(struct sip_pvt *p, struct sip_request *req, int t38action } } + if ((portno == -1) && (p->t38.state != T38_DISABLED)) { + ast_debug(3, "Have T.38 but no audio, accepting offer anyway\n"); + return 0; + } + /* 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));