Ejemplo n.º 1
0
// Creates a SDP body from transport address and list of media descriptors
// Use own list if given media list is 0
MimeSdpBody* SDPSession::createSDP(const char* addr, ObjList* mediaList)
{
    DDebug(m_parser,DebugAll,"SDPSession::createSDP('%s',%p) [%p]",addr,mediaList,this);
    if (!mediaList)
	mediaList = m_rtpMedia;
    // if we got no media descriptors we simply create no SDP
    if (!mediaList)
	return 0;
    if (m_sdpSession)
	++m_sdpVersion;
    else
	m_sdpVersion = m_sdpSession = Time::secNow();

    // no address means on hold or muted
    String origin;
    origin << "yate " << m_sdpSession << " " << m_sdpVersion;
    origin << " IN IP4 " << (addr ? addr : m_host.safe());
    String conn;
    conn << "IN IP4 " << (addr ? addr : "0.0.0.0");

    MimeSdpBody* sdp = new MimeSdpBody;
    sdp->addLine("v","0");
    sdp->addLine("o",origin);
    sdp->addLine("s",m_parser->m_sessionName);
    sdp->addLine("c",conn);
    sdp->addLine("t","0 0");

    Lock lock(m_parser);
    bool defcodecs = m_parser->m_codecs.getBoolValue("default",true);
    for (ObjList* ml = mediaList->skipNull(); ml; ml = ml->skipNext()) {
	SDPMedia* m = static_cast<SDPMedia*>(ml->get());
	String mline(m->fmtList());
	ObjList* l = mline.split(',',false);
	mline = *m;
	mline << " " << (m->localPort() ? m->localPort().c_str() : "0") << " " << m->transport();
	ObjList* map = m->mappings().split(',',false);
	ObjList rtpmap;
	String frm;
	int ptime = 0;
	ObjList* f = l;
	for (; f; f = f->next()) {
	    String* s = static_cast<String*>(f->get());
	    if (s) {
		int mode = 0;
		if (*s == "ilbc20")
		    ptime = mode = 20;
		else if (*s == "ilbc30")
		    ptime = mode = 30;
		else if (*s == "g729b")
		    continue;
		int payload = s->toInteger(SDPParser::s_payloads,-1);
		int defcode = payload;
		String tmp = *s;
		tmp << "=";
		for (ObjList* pl = map; pl; pl = pl->next()) {
		    String* mapping = static_cast<String*>(pl->get());
		    if (!mapping)
			continue;
		    if (mapping->startsWith(tmp)) {
			payload = -1;
			tmp = *mapping;
			tmp >> "=" >> payload;
			XDebug(m_parser,DebugAll,"RTP mapped payload %d for '%s' [%p]",
			    payload,s->c_str(),this);
			break;
		    }
		}
		if (payload >= 0) {
		    if (defcode < 0)
			defcode = payload;
		    const char* map = lookup(defcode,SDPParser::s_rtpmap);
		    if (map && m_parser->m_codecs.getBoolValue(*s,defcodecs && DataTranslator::canConvert(*s))) {
			frm << " " << payload;
			String* temp = new String("rtpmap:");
			*temp << payload << " " << map;
			rtpmap.append(temp);
			if (mode) {
			    temp = new String("fmtp:");
			    *temp << payload << " mode=" << mode;
			    rtpmap.append(temp);
			}
			if (*s == "g729") {
			    temp = new String("fmtp:");
			    *temp << payload << " annexb=" <<
				((0 != l->find("g729b")) ? "yes" : "no");
			    rtpmap.append(temp);
			}
			else if (*s == "amr") {
			    temp = new String("fmtp:");
			    *temp << payload << " octet-align=0";
			    rtpmap.append(temp);
			}
			else if (*s == "amr-o") {
			    temp = new String("fmtp:");
			    *temp << payload << " octet-align=1";
			    rtpmap.append(temp);
			}

			if(s->length()) {
			    String key("fmtp-");
			    key << *s;
			    for(unsigned int i = 0; i < m->length(); ++i) {
				const NamedString *ns = m->getParam(i);
				if(ns && ns->name() == key) {
				    temp = new String("fmtp:");
				    *temp << payload << " " << *ns;
				    rtpmap.append(temp);
				}
			    }
			}
		    }
		}
	    }
	}
	TelEngine::destruct(l);
	TelEngine::destruct(map);

	if ((m_rfc2833 >= 0) && frm && m->isAudio()) {
	    int rfc2833 = m->rfc2833().toInteger(m_rfc2833);
	    if (rfc2833 < 96 || rfc2833 > 127)
		rfc2833 = 101;
	    // claim to support telephone events
	    frm << " " << rfc2833;
	    String* s = new String;
	    *s << "rtpmap:" << rfc2833 << " telephone-event/8000";
	    rtpmap.append(s);
	}

	if (frm.null()) {
	    if (m->isAudio() || !m->fmtList()) {
		Debug(m_parser,DebugMild,"No formats for '%s', excluding from SDP [%p]",
		    m->c_str(),this);
		continue;
	    }
	    Debug(m_parser,DebugInfo,"Assuming formats '%s' for media '%s' [%p]",
		m->fmtList(),m->c_str(),this);
	    frm << " " << m->fmtList();
	    // brutal but effective
	    for (char* p = const_cast<char*>(frm.c_str()); *p; p++) {
		if (*p == ',')
		    *p = ' ';
	    }
	}

	if (ptime) {
	    String* temp = new String("ptime:");
	    *temp << ptime;
	    rtpmap.append(temp);
	}

	sdp->addLine("m",mline + frm);
	bool enc = false;
	if (m->isModified()) {
	    unsigned int n = m->length();
	    for (unsigned int i = 0; i < n; i++) {
		const NamedString* param = m->getParam(i);
		if (param) {
		    String tmp = param->name();
		    if (tmp.startsWith("fmtp-"))
			continue;
		    if (*param)
			tmp << ":" << *param;
		    sdp->addLine("a",tmp);
		    enc = enc || (param->name() == "encryption");
		}
	    }
	}
	for (f = rtpmap.skipNull(); f; f = f->skipNext()) {
	    String* s = static_cast<String*>(f->get());
	    if (s)
		sdp->addLine("a",*s);
	}
	if (addr && m->localCrypto()) {
	    sdp->addLine("a","crypto:" + m->localCrypto());
	    if (!enc)
		sdp->addLine("a","encryption:optional");
	}
    }
Ejemplo n.º 2
0
// Creates a SDP body from transport address and list of media descriptors
// Use own list if given media list is 0
MimeSdpBody* SDPSession::createSDP(const char* addr, ObjList* mediaList)
{
    DDebug(m_enabler,DebugAll,"SDPSession::createSDP('%s',%p) [%p]",addr,mediaList,m_ptr);
    if (!mediaList)
        mediaList = m_rtpMedia;
    // if we got no media descriptors we simply create no SDP
    if (!mediaList)
        return 0;
    if (m_sdpSession)
        ++m_sdpVersion;
    else
        m_sdpVersion = m_sdpSession = Time::secNow();

    // override the address with the externally advertised if needed
    if (addr && m_rtpNatAddr)
        addr = m_rtpNatAddr;
    if (!m_originAddr)
        m_originAddr = addr ? addr : m_host.safe();
    // no address means on hold or muted
    String origin;
    origin << "yate " << m_sdpSession << " " << m_sdpVersion;
    origin << " ";
    int f = addIP(origin,m_originAddr);
    String conn;
    addIP(conn,addr,f);

    MimeSdpBody* sdp = new MimeSdpBody;
    sdp->addLine("v","0");
    sdp->addLine("o",origin);
    sdp->addLine("s",m_parser->m_sessionName);
    sdp->addLine("c",conn);
    sdp->addLine("t","0 0");

    Lock lock(m_parser);
    bool defcodecs = m_parser->m_codecs.getBoolValue("default",true);
    for (ObjList* ml = mediaList->skipNull(); ml; ml = ml->skipNext()) {
        SDPMedia* m = static_cast<SDPMedia*>(ml->get());
        int rfc2833 = 0;
        if ((m_rfc2833 >= 0) && m->isAudio()) {
            if (!m_rtpForward) {
                rfc2833 = m->rfc2833().toInteger(m_rfc2833);
                if (rfc2833 < 96 || rfc2833 > 127)
                    rfc2833 = 101;
            }
            else if (m->rfc2833().toBoolean(true)) {
                rfc2833 = m->rfc2833().toInteger();
                if (rfc2833 < 96 || rfc2833 > 127)
                    rfc2833 = 0;
            }
        }
        String mline(m->fmtList());
        ObjList* l = mline.split(',',false);
        mline = *m;
        mline << " " << (m->localPort() ? m->localPort().c_str() : "0") << " " << m->transport();
        ObjList* map = m->mappings().split(',',false);
        ObjList rtpmap;
        ObjList* dest = &rtpmap;
        String frm;
        int ptime = 0;
        ObjList* f = l;
        for (; f; f = f->next()) {
            const String* s = static_cast<const String*>(f->get());
            if (s) {
                int mode = 0;
                if (*s == "g729b")
                    continue;
                int payload = s->toInteger(SDPParser::s_payloads,-1);
                int defcode = payload;
                String tmp = *s;
                tmp << "=";
                bool found = false;
                for (ObjList* pl = map; pl; pl = pl->next()) {
                    const String* mapping = static_cast<const String*>(pl->get());
                    if (!mapping)
                        continue;
                    if (mapping->startsWith(tmp)) {
                        payload = -1;
                        tmp = *mapping;
                        tmp >> "=" >> payload;
                        found = true;
                        XDebug(m_enabler,DebugAll,"RTP mapped payload %d for '%s' [%p]",
                               payload,s->c_str(),m_ptr);
                        break;
                    }
                    String tmp2 = *mapping;
                    int pload;
                    tmp2 >> "=" >> pload;
                    if (payload == pload) {
                        XDebug(m_enabler,DebugAll,"RTP conflict for payload %d, allocating new [%p]",
                               payload,m_ptr);
                        payload = -1;
                        u_int32_t bmap = 0;
                        for (ObjList* sl = map; sl; sl = sl->next()) {
                            mapping = static_cast<const String*>(sl->get());
                            if (!mapping)
                                continue;
                            tmp2 = *mapping;
                            pload = 0;
                            tmp2 >> "=" >> pload;
                            if (pload >= 96 && pload < 127)
                                bmap |= 1 << (pload - 96);
                        }
                        // allocate free and non-standard is possible
                        for (pload = 96; pload < 127; pload++) {
                            if (pload == rfc2833)
                                continue;
                            if (lookup(pload,SDPParser::s_rtpmap))
                                continue;
                            if ((bmap & (1 << (pload - 96))) == 0) {
                                payload = pload;
                                break;
                            }
                        }
                        if (payload >= 0)
                            break;
                        // none free, allocate from "standard" ones too
                        for (pload = 96; pload < 127; pload++) {
                            if (pload == rfc2833)
                                continue;
                            if ((bmap & (1 << (pload - 96))) == 0) {
                                payload = pload;
                                break;
                            }
                        }
                        break;
                    }
                }
                if (payload >= 0) {
                    if (!found) {
                        tmp = *s;
                        tmp << "=" << payload;
                        map->append(new String(tmp));
                    }
                    if (defcode < 0)
                        defcode = payload;
                    const char* map = lookup(defcode,SDPParser::s_rtpmap);
                    if (map && m_parser->m_codecs.getBoolValue(*s,defcodecs && DataTranslator::canConvert(*s))) {
                        if (*s == "ilbc20")
                            ptime = mode = 20;
                        else if (*s == "ilbc30")
                            ptime = mode = 30;
                        frm << " " << payload;
                        String* temp = new String("rtpmap:");
                        *temp << payload << " " << map;
                        dest = dest->append(temp);
                        if (mode) {
                            temp = new String("fmtp:");
                            *temp << payload << " mode=" << mode;
                            dest = dest->append(temp);
                        }
                        if (*s == "g729") {
                            temp = new String("fmtp:");
                            *temp << payload << " annexb=" <<
                                  ((0 != l->find("g729b")) ? "yes" : "no");
                            dest = dest->append(temp);
                        }
                        else if (*s == "amr") {
                            temp = new String("fmtp:");
                            *temp << payload << " octet-align=0";
                            dest = dest->append(temp);
                        }
                        else if (*s == "amr-o") {
                            temp = new String("fmtp:");
                            *temp << payload << " octet-align=1";
                            dest = dest->append(temp);
                        }
                    }
                }
            }
        }