Beispiel #1
0
// Set new media list. Return true if changed
bool SDPSession::setMedia(ObjList* media)
{
    if (media == m_rtpMedia)
        return false;
    DDebug(m_enabler,DebugAll,"SDPSession::setMedia(%p) [%p]",media,m_ptr);
    ObjList* tmp = m_rtpMedia;
    m_rtpMedia = media;
    bool chg = m_rtpMedia != 0;
    if (tmp) {
        chg = false;
        for (ObjList* o = tmp->skipNull(); o; o = o->skipNext()) {
            SDPMedia* m = static_cast<SDPMedia*>(o->get());
            if (media && m->sameAs(static_cast<SDPMedia*>((*media)[*m]),m_parser->ignorePort()))
                continue;
            chg = true;
            mediaChanged(*m);
        }
        TelEngine::destruct(tmp);
    }
    printRtpMedia("Set media");
    return chg;
}
Beispiel #2
0
NamedList& NamedList::setParam(const String& name, const char* value)
{
    XDebug(DebugInfo,"NamedList::setParam(\"%s\",\"%s\")",name.c_str(),value);
    ObjList *p = m_params.skipNull();
    while (p) {
        NamedString *s = static_cast<NamedString*>(p->get());
        if (s->name() == name) {
            *s = value;
	    return *this;
	}
	ObjList* next = p->skipNext();
	if (next)
	    p = next;
	else
	    break;
    }
    if (p)
	p->append(new NamedString(name,value));
    else
	m_params.append(new NamedString(name,value));
    return *this;
}
Beispiel #3
0
bool ExpEvaluator::runAllFields(ObjList& stack, GenObject* context) const
{
    DDebug(this,DebugAll,"runAllFields(%p,%p)",&stack,context);
    bool ok = true;
    for (ObjList* l = stack.skipNull(); l; l = l->skipNext()) {
	const ExpOperation* o = static_cast<const ExpOperation*>(l->get());
	if (o->barrier())
	    break;
	if (o->opcode() != OpcField)
	    continue;
	ObjList tmp;
	if (runField(tmp,*o,context)) {
	    ExpOperation* val = popOne(tmp);
	    if (val)
		l->set(val);
	    else
		ok = false;
	}
	else
	    ok = false;
    }
    return ok;
}
Beispiel #4
0
// Repeatedly calls dispatchRtp() for each media in the list
// Update it on success. Remove it on failure
bool SDPSession::dispatchRtp(const char* addr, bool start, RefObject* context)
{
    if (!m_rtpMedia)
	return false;
    DDebug(m_parser,DebugAll,"SDPSession::dispatchRtp(%s,%u,%p) [%p]",
	addr,start,context,this);
    bool ok = false;
    ObjList* o = m_rtpMedia->skipNull();
    while (o) {
	SDPMedia* m = static_cast<SDPMedia*>(o->get());
	if (dispatchRtp(m,addr,start,true,context)) {
	    ok = true;
	    o = o->skipNext();
	}
	else {
	    Debug(m_parser,DebugMild,
		"Removing failed SDP media '%s' format '%s' from offer [%p]",
		m->c_str(),m->format().safe(),this);
	    o->remove();
	    o = o->skipNull();
	}
    }
    return ok;
}
Beispiel #5
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");
	}
    }
Beispiel #6
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);
                        }
                    }
                }
            }
        }
Beispiel #7
0
// Create a buffer containing the byte representation of a message to be sent
//  and another one with the header
bool ETSIModem::createMsg(NamedList& params, DataBlock& data)
{
    int type = lookup(params,s_msg);
    switch (type) {
	case MsgCallSetup:
	    break;
	case MsgMWI:
	case MsgCharge:
	case MsgSMS:
	    Debug(this,DebugStub,"Create message '%s' not implemented [%p]",
		params.c_str(),this);
	    return false;
	default:
	    Debug(this,DebugNote,"Can't create unknown message '%s' [%p]",
		params.c_str(),this);
	    return false;
    }

    ObjList msg;
    bool fail = !params.getBoolValue("force-send",true);

    // DateTime - ETSI EN 300 659-3 - 5.4.1
    String datetime = params.getValue("datetime");
    unsigned char dt[4];
    bool ok = false;
    if (datetime.isBoolean())
	if (datetime.toBoolean())
	    ok = getDateTime(dt);
	else ;
    else
	ok = getDateTime(dt,&datetime);
    if (ok) {
	DataBlock* dtParam = new DataBlock(0,10);
	unsigned char* d = (unsigned char*)dtParam->data();
	d[0] = DateTime;
	d[1] = 8;
	// Set date and time: %.2d%.2d%.2d%.2d month:day:hour:minute
	for (int i = 0, j = 2; i < 4; i++, j += 2) {
	    d[j] = '0' + dt[i] / 10;
	    d[j+1] = '0' + dt[i] % 10;
	}
	msg.append(dtParam);
    }
    else
	DDebug(this,DebugInfo,"Can't set datetime parameter from '%s' [%p]",
	    datetime.c_str(),this);

    // CallerId/CallerIdReason - ETSI EN 300 659-3 - 5.4.2: Max caller id 20
    // Parameter is missing: append reason (default caller absence: 0x4f: unavailable)
    int res = appendParam(msg,params,CallerId,20,fail);
    if (res == -1)
	return false;
    if (!res)
	appendParam(msg,params,CallerIdReason,s_dict_callerAbsence,0x4f);

    // CallerName/CallerNameReason - ETSI EN 300 659-3 - 5.4.5: Max caller name 50
    // Parameter is missing: append reason (default callername absence: 0x4f: unavailable)
    res = appendParam(msg,params,CallerName,50,fail);
    if (res == -1)
	return false;
    if (!res)
	appendParam(msg,params,CallerNameReason,s_dict_callerAbsence,0x4f);

    // Build message
    unsigned char len = 0;
    unsigned char hdr[2] = {type};
    data.assign(&hdr,sizeof(hdr));

    for (ObjList* o = msg.skipNull(); o; o = o->skipNext()) {
	DataBlock* msgParam = static_cast<DataBlock*>(o->get());
	if (len + msgParam->length() > 255) {
	    if (!fail) {
		Debug(this,DebugNote,"Trucating %s message length to %u bytes [%p]",
		    params.c_str(),data.length(),this);
		break;
	    }
	    params.setParam("error","message-too-long");
	    return false;
	}
	len += msgParam->length();
	data += *msgParam;
    }
    if (!len) {
	params.setParam("error","empty-message");
	return false;
    }

    unsigned char* buf = ((unsigned char*)(data.data()));
    buf[1] = len;
    m_chksum = 0;
    for (unsigned int i = 0; i < data.length(); i++)
	m_chksum += buf[i];
    unsigned char crcVal = 256 - (m_chksum & 0xff);
    FSKModem::addRaw(data,&crcVal,1);
    return true;
}