示例#1
0
NamedList& NamedList::copySubParams(const NamedList& original, const String& prefix,
    bool skipPrefix, bool replace)
{
    XDebug(DebugInfo,"NamedList::copySubParams(%p,\"%s\",%s,%s) [%p]",
	&original,prefix.c_str(),String::boolText(skipPrefix),
	String::boolText(replace),this);
    if (prefix) {
	unsigned int offs = skipPrefix ? prefix.length() : 0;
	ObjList* dest = &m_params;
	for (const ObjList* l = original.m_params.skipNull(); l; l = l->skipNext()) {
	    const NamedString* s = static_cast<const NamedString*>(l->get());
	    if (s->name().startsWith(prefix)) {
		const char* name = s->name().c_str() + offs;
		if (!*name)
		    continue;
		if (!replace)
		    dest = dest->append(new NamedString(name,*s));
		else if (offs)
		    setParam(name,*s);
		else
		    setParam(s->name(),*s);
	    }
	}
    }
    return *this;
}
示例#2
0
// Insert a record into a list in the proper location
// Order records ascending by their order
// Look at ascPref for records with the same order
bool DnsRecord::insert(ObjList& list, DnsRecord* rec, bool ascPref)
{
    if (!rec || list.find(rec))
	return false;
    XDebug(DebugAll,"DnsRecord::insert(%p) order=%d pref=%d",rec,rec->order(),rec->pref());
    ObjList* o = list.skipNull();
    for (; o; o = o->skipNext()) {
	DnsRecord* crt = static_cast<DnsRecord*>(o->get());
	if (rec->order() > crt->order())
	    continue;
	if (rec->order() == crt->order()) {
	    for (; o; o = o->skipNext()) {
		DnsRecord* crt = static_cast<DnsRecord*>(o->get());
		if (crt->order() != rec->order())
		    break;
		if (crt->pref() == rec->pref())
		    continue;
		if (ascPref == (rec->pref() < crt->pref()))
		    break;
	    }
	}
	break;
    }
    if (o)
	o->insert(rec);
    else
	list.append(rec);
    return true;
}
示例#3
0
// Copy a SrvRecord list into another one
void SrvRecord::copy(ObjList& dest, const ObjList& src)
{
    dest.clear();
    for (ObjList* o = src.skipNull(); o; o = o->skipNext()) {
	SrvRecord* rec = static_cast<SrvRecord*>(o->get());
	dest.append(new SrvRecord(rec->order(),rec->pref(),rec->address(),rec->port()));
    }
}
示例#4
0
// Append a parameter to a buffer from a list or dictionary
void appendParam(ObjList& msg, NamedList& params, unsigned char value,
	TokenDict* dict, unsigned char defValue)
{
    unsigned char a[3] = {value,1};
    const char* name = lookup(value,ETSIModem::s_msgParams);
    a[2] = lookup(params.getValue(name),dict,defValue);
    msg.append(new DataBlock(a,sizeof(a)));
}
示例#5
0
NamedList::NamedList(const NamedList& original)
    : String(original)
{
    ObjList* dest = &m_params;
    for (const ObjList* l = original.m_params.skipNull(); l; l = l->skipNext()) {
	const NamedString* p = static_cast<const NamedString*>(l->get());
	dest = dest->append(new NamedString(p->name(),*p));
    }
}
示例#6
0
文件: Thread.cpp 项目: 0x7678/evilbts
ThreadPrivate::ThreadPrivate(Thread* t,const char* name)
    : m_thread(t), m_counter(0),
      m_running(false), m_started(false), m_updest(true), m_cancel(false), m_name(name)
{
#ifdef DEBUG
    Debugger debug("ThreadPrivate::ThreadPrivate","(%p,\"%s\") [%p]",t,name,this);
#endif
    // Inherit object counter of creating thread
    m_counter = Thread::getCurrentObjCounter(true);
    Lock lock(s_tmutex);
    s_threads.append(this);
}
示例#7
0
bool ExpEvaluator::runFunction(ObjList& stack, const ExpOperation& oper) const
{
    DDebug(DebugAll,"runFunction(%p,'%s' %ld) ext=%p",
           &stack,oper.name().c_str(),oper.number(),(void*)m_extender);
    if (oper.name() == YSTRING("chr")) {
        String res;
        for (long int i = oper.number(); i; i--) {
            ExpOperation* o = popOne(stack);
            if (!o)
                return gotError("ExpEvaluator stack underflow");
            res = String((char)o->number()) + res;
            TelEngine::destruct(o);
        }
        stack.append(new ExpOperation(res));
        return true;
    }
    if (oper.name() == YSTRING("now")) {
        if (oper.number())
            return gotError("Function expects no arguments");
        stack.append(new ExpOperation(Time::secNow()));
        return true;
    }
    return m_extender && m_extender->runFunction(this,stack,oper);
}
示例#8
0
NamedList& NamedList::copyParam(const NamedList& original, const String& name, char childSep)
{
    XDebug(DebugInfo,"NamedList::copyParam(%p,\"%s\",'%.1s')",
	&original,name.c_str(),&childSep);
    if (!childSep) {
	// faster and simpler - used in most cases
	const NamedString* s = original.getParam(name);
	return s ? setParam(name,*s) : clearParam(name);
    }
    clearParam(name,childSep);
    String tmp;
    tmp << name << childSep;
    ObjList* dest = &m_params;
    for (const ObjList* l = original.m_params.skipNull(); l; l = l->skipNext()) {
	const NamedString* s = static_cast<const NamedString*>(l->get());
        if ((s->name() == name) || s->name().startsWith(tmp))
	    dest = dest->append(new NamedString(s->name(),*s));
    }
    return *this;
}
示例#9
0
bool MrcpConnection::init(Message& msg, const char* target)
{
    if (!target)
	return false;
    s_mutex.lock();
    if (!s_conns.find(this))
	s_conns.append(this);
    s_mutex.unlock();
    Message m("call.execute");
    m.addParam("id",id());
    m.addParam("callto",target);
    m.copyParam(msg,"caller");
    m.copyParam(msg,"called");
    m.addParam("media",String::boolText(true));
    m.addParam("media_application",String::boolText(true));
    m.addParam("transport_application","TCP/MRCPv2");
    m.addParam("formats_application","1"); // defined by the standard
    m.userData(this);
    return Engine::dispatch(m);
}
示例#10
0
// Append a parameter to a buffer
// Truncate it or set error if fail is true and parameter length exceeds maxLen
// Return: 0 if the parameter is missing
//         -1 if the parameter is too long
//         1 on success
int appendParam(ObjList& msg, NamedList& params, unsigned char value,
	unsigned char maxLen, bool fail)
{
    NamedString* ns = params.getParam(lookup(value,ETSIModem::s_msgParams));
    if (!ns)
	return 0;
    unsigned char len = ns->length();
    if (len > maxLen) {
	if (fail) {
	    params.setParam("error",ns->name() + "-too-long");
	    return -1;
	}
	len = maxLen;
    }
    DataBlock* data = new DataBlock;
    unsigned char a[2] = {value,len};
    FSKModem::addRaw(*data,a,sizeof(a));
    FSKModem::addRaw(*data,(void*)ns->c_str(),len);
    msg.append(data);
    return 1;
}
示例#11
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;
}
示例#12
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;
}
示例#13
0
bool ExpEvaluator::runOperation(ObjList& stack, const ExpOperation& oper) const
{
    DDebug(DebugAll,"runOperation(%p,%u) %s",&stack,oper.opcode(),getOperator(oper.opcode()));
    switch (oper.opcode()) {
    case OpcPush:
        stack.append(new ExpOperation(oper));
        break;
    case OpcAnd:
    case OpcOr:
    case OpcXor:
    case OpcShl:
    case OpcShr:
    case OpcAdd:
    case OpcSub:
    case OpcMul:
    case OpcDiv:
    case OpcMod:
    case OpcEq:
    case OpcNe:
    case OpcLt:
    case OpcGt:
    case OpcLe:
    case OpcGe:
    {
        ExpOperation* op2 = popOne(stack);
        ExpOperation* op1 = popOne(stack);
        if (!op1 || !op2) {
            TelEngine::destruct(op1);
            TelEngine::destruct(op2);
            return gotError("ExpEvaluator stack underflow");
        }
        switch (oper.opcode()) {
        case OpcDiv:
        case OpcMod:
            if (!op2->number())
                return gotError("Division by zero");
        default:
            break;
        }
        long int val = 0;
        switch (oper.opcode()) {
        case OpcAnd:
            val = op1->number() & op2->number();
            break;
        case OpcOr:
            val = op1->number() | op2->number();
            break;
        case OpcXor:
            val = op1->number() ^ op2->number();
            break;
        case OpcShl:
            val = op1->number() << op2->number();
            break;
        case OpcShr:
            val = op1->number() >> op2->number();
            break;
        case OpcAdd:
            val = op1->number() + op2->number();
            break;
        case OpcSub:
            val = op1->number() - op2->number();
            break;
        case OpcMul:
            val = op1->number() * op2->number();
            break;
        case OpcDiv:
            val = op1->number() / op2->number();
            break;
        case OpcMod:
            val = op1->number() % op2->number();
            break;
        case OpcLt:
            val = (op1->number() < op2->number()) ? 1 : 0;
            break;
        case OpcGt:
            val = (op1->number() > op2->number()) ? 1 : 0;
            break;
        case OpcLe:
            val = (op1->number() <= op2->number()) ? 1 : 0;
            break;
        case OpcGe:
            val = (op1->number() >= op2->number()) ? 1 : 0;
            break;
        case OpcEq:
            val = (*op1 == *op2) ? 1 : 0;
            break;
        case OpcNe:
            val = (*op1 != *op2) ? 1 : 0;
            break;
        default:
            break;
        }
        TelEngine::destruct(op1);
        TelEngine::destruct(op2);
        DDebug(DebugAll,"Numeric result: %lu",val);
        stack.append(new ExpOperation(val));
    }
    break;
    case OpcLAnd:
    case OpcLOr:
    {
        ExpOperation* op2 = popOne(stack);
        ExpOperation* op1 = popOne(stack);
        if (!op1 || !op2) {
            TelEngine::destruct(op1);
            TelEngine::destruct(op2);
            return gotError("ExpEvaluator stack underflow");
        }
        bool val = false;
        switch (oper.opcode()) {
        case OpcLAnd:
            val = op1->number() && op2->number();
            break;
        case OpcLOr:
            val = op1->number() || op2->number();
            break;
        default:
            break;
        }
        TelEngine::destruct(op1);
        TelEngine::destruct(op2);
        DDebug(DebugAll,"Bool result: '%s'",String::boolText(val));
        stack.append(new ExpOperation(val ? 1 : 0));
    }
    break;
    case OpcCat:
    {
        ExpOperation* op2 = popOne(stack);
        ExpOperation* op1 = popOne(stack);
        if (!op1 || !op2) {
            TelEngine::destruct(op1);
            TelEngine::destruct(op2);
            return gotError("ExpEvaluator stack underflow");
        }
        String val = *op1 + *op2;
        TelEngine::destruct(op1);
        TelEngine::destruct(op2);
        DDebug(DebugAll,"String result: '%s'",val.c_str());
        stack.append(new ExpOperation(val));
    }
    break;
    case OpcAs:
    {
        ExpOperation* op2 = popOne(stack);
        ExpOperation* op1 = popOne(stack);
        if (!op1 || !op2) {
            TelEngine::destruct(op1);
            TelEngine::destruct(op2);
            return gotError("ExpEvaluator stack underflow");
        }
        stack.append(new ExpOperation(*op1,*op2));
        TelEngine::destruct(op1);
        TelEngine::destruct(op2);
    }
    break;
    case OpcFunc:
        return runFunction(stack,oper);
    case OpcField:
        return runField(stack,oper);
    default:
        Debug(DebugStub,"Please implement operation %u",oper.opcode());
        return false;
    }
    return true;
}
示例#14
0
bool ExpEvaluator::trySimplify()
{
    DDebug(DebugInfo,"trySimplify");
    bool done = false;
    for (unsigned int i = 0; i < m_opcodes.length(); i++) {
        ExpOperation* o = static_cast<ExpOperation*>(m_opcodes[i]);
        if (!o)
            continue;
        switch (o->opcode()) {
        case OpcLAnd:
        case OpcLOr:
        case OpcLXor:
        case OpcAnd:
        case OpcOr:
        case OpcXor:
        case OpcShl:
        case OpcShr:
        case OpcAdd:
        case OpcSub:
        case OpcMul:
        case OpcDiv:
        case OpcMod:
        case OpcCat:
        case OpcEq:
        case OpcNe:
        case OpcLt:
        case OpcGt:
        case OpcLe:
        case OpcGe:
            if (i >= 2) {
                ExpOperation* op2 = static_cast<ExpOperation*>(m_opcodes[i-1]);
                ExpOperation* op1 = static_cast<ExpOperation*>(m_opcodes[i-2]);
                if (!op1 || !op2)
                    continue;
                if (o->opcode() == OpcLAnd || o->opcode() == OpcAnd || o->opcode() == OpcMul) {
                    if ((op1->opcode() == OpcPush && !op1->number() && op2->opcode() == OpcField) ||
                            (op2->opcode() == OpcPush && !op2->number() && op1->opcode() == OpcField)) {
                        (m_opcodes+i)->set(new ExpOperation(0));
                        m_opcodes.remove(op1);
                        m_opcodes.remove(op2);
                        i -= 2;
                        done = true;
                        continue;
                    }
                }
                if (o->opcode() == OpcLOr) {
                    if ((op1->opcode() == OpcPush && op1->number() && op2->opcode() == OpcField) ||
                            (op2->opcode() == OpcPush && op2->number() && op1->opcode() == OpcField)) {
                        (m_opcodes+i)->set(new ExpOperation(1));
                        m_opcodes.remove(op1);
                        m_opcodes.remove(op2);
                        i -= 2;
                        done = true;
                        continue;
                    }
                }
                if ((op1->opcode() == OpcPush) && (op2->opcode() == OpcPush)) {
                    ObjList stack;
                    stack.append(new ExpOperation(*op1));
                    stack.append(new ExpOperation(*op2));
                    if (runOperation(stack,*o)) {
                        // replace operators and operation with computed constant
                        (m_opcodes+i)->set(popOne(stack));
                        m_opcodes.remove(op1);
                        m_opcodes.remove(op2);
                        i -= 2;
                        done = true;
                    }
                }
            }
        default:
            break;
        }
    }
    return done;
}
示例#15
0
文件: session.cpp 项目: wdaniels/yate
// 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");
	}
    }
示例#16
0
文件: session.cpp 项目: wdaniels/yate
// Update from parameters. Build a default SDP if no media is found in params
bool SDPSession::updateSDP(const NamedList& params)
{
    DDebug(m_parser,DebugAll,"SDPSession::updateSdp('%s') [%p]",params.c_str(),this);
    bool defaults = true;
    const char* sdpPrefix = params.getValue("osdp-prefix","osdp");
    ObjList* lst = 0;
    unsigned int n = params.length();
    String defFormats;
    m_parser->getAudioFormats(defFormats);
    for (unsigned int i = 0; i < n; i++) {
	const NamedString* p = params.getParam(i);
	if (!p)
	    continue;
	// search for rtp_port or rtp_port_MEDIANAME parameters
	String tmp(p->name());
	if (!tmp.startSkip("media",false))
	    continue;
	if (tmp && (tmp[0] != '_'))
	    continue;
	// since we found at least one media declaration disable defaults
	defaults = false;
	// now tmp holds the suffix for the media, null for audio
	bool audio = tmp.null();
	// check if media is supported, default only for audio
	if (!p->toBoolean(audio))
	    continue;
	String fmts = params.getValue("formats" + tmp);
	if (audio && fmts.null())
	    fmts = defFormats;
	if (fmts.null())
	    continue;
	String trans = params.getValue("transport" + tmp,"RTP/AVP");
	String crypto;
	if (m_secure)
	    crypto = params.getValue("crypto" + tmp);
	if (audio)
	    tmp = "audio";
	else
	    tmp >> "_";
	SDPMedia* rtp = 0;
	// try to take the media descriptor from the old list
	if (m_rtpMedia) {
	    ObjList* om = m_rtpMedia->find(tmp);
	    if (om)
		rtp = static_cast<SDPMedia*>(om->remove(false));
	}
	bool append = false;
	if (rtp)
	    rtp->update(fmts);
	else {
	    rtp = new SDPMedia(tmp,trans,fmts);
	    append = true;
	}
	rtp->crypto(crypto,false);
	if (sdpPrefix) {
	    for (unsigned int j = 0; j < n; j++) {
		const NamedString* param = params.getParam(j);
		if (!param)
		    continue;
		tmp = param->name();
		if (tmp.startSkip(sdpPrefix + rtp->suffix() + "_",false) && (tmp.find('_') < 0))
		    rtp->parameter(tmp,*param,append);
	    }
	}
	if (!lst)
	    lst = new ObjList;
	lst->append(rtp);
    }
    if (defaults && !lst) {
	lst = new ObjList;
	lst->append(new SDPMedia("audio","RTP/AVP",params.getValue("formats",defFormats)));
    }
    return setMedia(lst);
}
示例#17
0
文件: session.cpp 项目: hewu2008/yate
// 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);
                        }
                    }
                }
            }
        }
示例#18
0
// Parse a received buffer according to RFC 3435
// See Appendix A for the grammar
bool MGCPMessage::parse(MGCPEngine* engine, ObjList& dest,
	const unsigned char* buffer, unsigned int len, const char* sdpType)
{
    if (!buffer)
	return false;

#ifdef PARSER_DEBUG
    String t((const char*)buffer,len);
    Debug(engine,DebugAll,"Parse received buffer\r\n%s",t.c_str());
#endif

    int errorCode = 510;              // Protocol error
    unsigned int trans = 0;
    String error;
    unsigned int crt = 0;

    while (crt < len && !error) {
	unsigned int count = 0;
	const char* line = 0;

	// Skip empty lines before a message line and skip trailing blanks on the message line
	while (crt < len) {
	    line = getLine(buffer,len,crt,count);
	    if (!line) {
		error = "Invalid end-of-line";
		break;
	    }
	    // Exit loop if the line is not empty
	    if (count)
		break;
	}
	if (!count || error)
	    break;

	// *** Decode the message line
	MGCPMessage* msg = decodeMessage(line,count,trans,error,engine);
	if (!msg)
	    break;
	dest.append(msg);

#ifdef PARSER_DEBUG
	String m((const char*)line,count);
	Debug(engine,DebugAll,"Decoded message: %s",m.c_str());
#endif

	// *** Decode parameters
	if (decodeParams(buffer,len,crt,msg,error,engine))
	    continue;
	if (error) {
	    if (msg->isCommand())
		trans = msg->transactionId();
	    break;
	}
	if (crt >= len)
	    break;

	// *** Decode SDP
	// Decode SDPs until the end of buffer or
        //  a line containing a dot (message separator in a piggybacked block)
	// SDPs are separated by an empty line
	int empty = 0;
	while (empty < 2) {
	    // Skip until an empty line, a line containing a dot or end of buffer
	    unsigned int start = crt;
	    unsigned int sdpLen = 0;
	    while (true) {
		line = getLine(buffer,len,crt,count);
		if (!line) {
		    error = "Invalid end-of-line";
		    break;
		}
		if (!count || (count == 1 && (*line == '.' || !*line))) {
		    if (!count)
			empty++;
		    else
			empty = 3;
		    break;
		}
		empty = 0;
		sdpLen = crt - start;
	    }
	    if (error)
		break;
	    if (sdpLen)
		msg->sdp.append(new MimeSdpBody(sdpType,(const char*)buffer+start,sdpLen));
	}

	// Found 2 empty lines: skip until end of buffer or line containing '.' or non empty line
	if (empty == 2) {
	    unsigned int start = crt;
	    while (true) {
		line = getLine(buffer,len,crt,count);
		if (!line) {
		    error = "Invalid end-of-line";
		    break;
		}
		if (!count) {
		    if (crt == len)
			break;
		    continue;
		}
		// Fallback with current index if found non empty line which doesn't start with '.'
		if (*line && *line != '.')
		    crt = start;
		break;
	    }
	}
    }
    if (!error)
	return true;

    dest.clear();
    if (trans && trans <= 999999999)
	dest.append(new MGCPMessage(engine,0,errorCode,trans,0,0));
    Debug(engine,DebugNote,"Parser error: %s",error.c_str());
    return false;
}