Ejemplo n.º 1
0
void RTPGroup::run()
{
    DDebug(DebugInfo,"RTPGroup::run() [%p]",this);
    bool ok = true;
    while (ok) {
	unsigned long msec = m_sleep;
	if (msec < s_sleep)
	    msec = s_sleep;
	lock();
	Time t;
	ObjList* l = &m_processors;
	m_listChanged = false;
	for (ok = false;l;l = l->next()) {
	    RTPProcessor* p = static_cast<RTPProcessor*>(l->get());
	    if (p) {
		ok = true;
		p->timerTick(t);
		// the list is protected from other threads but can be changed
		//  from this one so if it happened we just break out and try
		//  again later rather than using an expensive ListIterator
		if (m_listChanged)
		    break;
	    }
	}
	unlock();
	Thread::msleep(msec,true);
    }
    DDebug(DebugInfo,"RTPGroup::run() ran out of processors [%p]",this);
}
Ejemplo n.º 2
0
bool HashList::resync()
{
    XDebug(DebugAll,"HashList::resync() [%p]",this);
    bool moved = false;
    for (unsigned int n = 0; n < m_size; n++) {
        ObjList* l = m_lists[n];
        while (l) {
            GenObject* obj = l->get();
            if (obj) {
                unsigned int i = obj->toString().hash() % m_size;
                if (i != n) {
                    bool autoDel = l->autoDelete();
                    m_lists[n]->remove(obj,false);
                    if (!m_lists[i])
                        m_lists[i] = new ObjList;
                    m_lists[i]->append(obj)->setDelete(autoDel);
                    moved = true;
                    continue;
                }
            }
            l = l->next();
        }
    }
    return moved;
}
Ejemplo n.º 3
0
GenObject* ObjList::remove(bool delobj)
{
    GenObject *tmp = m_obj;

    if (m_next) {
	ObjList *n = m_next;
	m_next = n->next();
	m_obj = n->get();
	m_delete = n->m_delete;
	n->m_obj = 0;
	n->m_next = 0;
	n->destruct();
    }
    else
	m_obj = 0;

    if (delobj && tmp) {
	XDebug(DebugInfo,"ObjList::remove() deleting %p",tmp);
	// Don't use TelEngine::destruct(): the compiler will call the non-template
	// function (which doesn't reset the pointer)
	tmp->destruct();
	tmp = 0;
    }
    return tmp;
}
Ejemplo n.º 4
0
void Socket::timerTick(const Time& when)
{
    for (ObjList* l = &m_filters; l; l = l->next()) {
	SocketFilter* filter = static_cast<SocketFilter*>(l->get());
	if (filter)
	    filter->timerTick(when);
    }
}
Ejemplo n.º 5
0
ObjList* ObjList::operator+(int index) const
{
    if (index < 0)
	return 0;
    ObjList *obj = const_cast<ObjList*>(this);
    for (;obj;obj=obj->next(),index--)
	if (!index) break;
    return obj;
}
Ejemplo n.º 6
0
ExpOperation* ExpEvaluator::popOpcode()
{
    ObjList* l = &m_opcodes;
    for (ObjList* p = l; p; p = p->next()) {
	if (p->get())
	    l = p;
    }
    return static_cast<ExpOperation*>(l->remove(false));
}
Ejemplo n.º 7
0
ToneConsumer::ToneConsumer(const String& id, const String& name)
    : m_id(id), m_name(name), m_mode(Mono),
      m_detFax(true), m_detCont(false), m_detDtmf(true), m_detDnis(false),
      m_fax(s_paramsCNG), m_cont(s_paramsCOTv)
{ 
    Debug(&plugin,DebugAll,"ToneConsumer::ToneConsumer(%s,'%s') [%p]",
	id.c_str(),name.c_str(),this);
    for (int i = 0; i < 4; i++) {
	m_dtmfL[i].assign(s_paramsDtmfL[i]);
	m_dtmfH[i].assign(s_paramsDtmfH[i]);
    }
    init();
    String tmp = name;
    tmp.startSkip("tone/",false);
    if (tmp.startSkip("mixed/",false))
	m_mode = Mixed;
    else if (tmp.startSkip("left/",false))
	m_mode = Left;
    else if (tmp.startSkip("right/",false))
	m_mode = Right;
    else tmp.startSkip("mono/",false);
    if (m_mode != Mono)
	m_format = "2*slin";
    if (tmp && (tmp != "*")) {
	// individual detection requested
	m_detFax = m_detCont = m_detDtmf = m_detDnis = false;
	ObjList* k = tmp.split(',',false);
	for (ObjList* l = k; l; l = l->next()) {
	    String* s = static_cast<String*>(l->get());
	    if (!s)
		continue;
	    m_detFax = m_detFax || (*s == "fax");
	    m_detCont = m_detCont || (*s == "cotv");
	    m_detDtmf = m_detDtmf || (*s == "dtmf");
	    if (*s == "rfax") {
		// detection of receiving Fax requested
		m_fax.assign(s_paramsCED);
		m_detFax = true;
	    }
	    else if (*s == "cots") {
		// detection of COT Send tone requested
		m_cont.assign(s_paramsCOTs);
		m_detCont = true;
	    }
	    else if (*s == "callsetup") {
		// call setup info in the form *ANI*DNIS*
		m_detDnis = true;
	    }
	}
	TelEngine::destruct(k);
    }
    s_mutex.lock();
    s_count++;
    s_mutex.unlock();
}
Ejemplo n.º 8
0
SIPTransaction* SIPEngine::addMessage(SIPMessage* message)
{
    DDebug(this,DebugInfo,"addMessage(%p) [%p]",message,this);
    if (!message)
	return 0;
    // make sure outgoing messages are well formed
    if (message->isOutgoing())
	message->complete(this);
    // locate the branch parameter of last Via header - added by the UA
    const MimeHeaderLine* hl = message->getLastHeader("Via");
    if (!hl)
#ifdef SIP_STRICT
	return 0;
#else
	Debug(this,DebugMild,"Received message with no Via header! (sender bug)");
#endif
    const NamedString* br = hl ? hl->getParam("branch") : 0;
    String branch;
    if (br && br->startsWith("z9hG4bK"))
	branch = *br;
    Lock lock(this);
    SIPTransaction* forked = 0;
    ObjList* l = &m_transList;
    for (; l; l = l->next()) {
	SIPTransaction* t = static_cast<SIPTransaction*>(l->get());
	if (!t)
	    continue;
	switch (t->processMessage(message,branch)) {
	    case SIPTransaction::Matched:
		return t;
	    case SIPTransaction::NoDialog:
		forked = t;
		break;
	    case SIPTransaction::NoMatch:
	    default:
		break;
	}
    }
    if (forked)
	return forkInvite(message,forked);

    if (message->isAnswer()) {
	Debug(this,DebugInfo,"Message %p was an unhandled answer [%p]",message,this);
	return 0;
    }
    if (message->isACK()) {
	DDebug(this,DebugAll,"Message %p was an unhandled ACK [%p]",message,this);
	return 0;
    }
    message->complete(this);
    return new SIPTransaction(message,this,message->isOutgoing());
}
Ejemplo n.º 9
0
bool Socket::applyFilters(void* buffer, int length, int flags, const struct sockaddr* addr, socklen_t adrlen)
{
    if ((length <= 0) || !buffer)
	return false;
    if (!addr)
	adrlen = 0;
    for (ObjList* l = &m_filters; l; l = l->next()) {
	SocketFilter* filter = static_cast<SocketFilter*>(l->get());
	if (filter && filter->received(buffer,length,flags,addr,adrlen))
	    return true;
    }
    return false;
}
Ejemplo n.º 10
0
NamedList& NamedList::clearParam(const String& name, char childSep)
{
    XDebug(DebugInfo,"NamedList::clearParam(\"%s\",'%.1s')",
	name.c_str(),&childSep);
    String tmp;
    if (childSep)
	tmp << name << childSep;
    ObjList *p = &m_params;
    while (p) {
        NamedString *s = static_cast<NamedString *>(p->get());
        if (s && ((s->name() == name) || s->name().startsWith(tmp)))
            p->remove();
	else
	    p = p->next();
    }
    return *this;
}
Ejemplo n.º 11
0
void RTPGroup::cleanup()
{
    DDebug(DebugInfo,"RTPGroup::cleanup() [%p]",this);
    lock();
    m_listChanged = true;
    ObjList* l = &m_processors;
    while (l) {
	RTPProcessor* p = static_cast<RTPProcessor*>(l->get());
	if (p) {
	    p->group(0);
	    if (p != static_cast<RTPProcessor*>(l->get()))
		continue;
	}
	l = l->next();
    }
    m_processors.clear();
    unlock();
}
Ejemplo n.º 12
0
GenObject* ObjList::remove(bool delobj)
{
    GenObject *tmp = m_obj;

    if (m_next) {
	ObjList *n = m_next;
	m_next = n->next();
	m_obj = n->get();
	m_delete = n->m_delete;
	n->m_obj = 0;
	n->m_next = 0;
	n->destruct();
    }
    else
	m_obj = 0;

    if (delobj && tmp) {
	XDebug(DebugInfo,"ObjList::remove() deleting %p",tmp);
	TelEngine::destruct(tmp);
    }
    return tmp;
}
Ejemplo n.º 13
0
bool MessageDispatcher::install(MessageHandler* handler)
{
    DDebug(DebugAll,"MessageDispatcher::install(%p)",handler);
    if (!handler)
	return false;
    Lock lock(this);
    ObjList *l = m_handlers.find(handler);
    if (l)
	return false;
    unsigned p = handler->priority();
    int pos = 0;
    for (l=&m_handlers; l; l=l->next(),pos++) {
	MessageHandler *h = static_cast<MessageHandler *>(l->get());
	if (!h)
	    continue;
	if (h->priority() < p)
	    continue;
	if (h->priority() > p)
	    break;
	// at the same priority we sort them in pointer address order
	if (h > handler)
	    break;
    }
    m_changes++;
    if (l) {
	XDebug(DebugAll,"Inserting handler [%p] on place #%d",handler,pos);
	l->insert(handler);
    }
    else {
	XDebug(DebugAll,"Appending handler [%p] on place #%d",handler,pos);
	m_handlers.append(handler);
    }
    handler->m_dispatcher = this;
    if (handler->null())
	Debug(DebugInfo,"Registered broadcast message handler %p",handler);
    return true;
}
Ejemplo n.º 14
0
bool MessageDispatcher::dispatch(Message& msg)
{
#ifdef XDEBUG
    Debugger debug("MessageDispatcher::dispatch","(%p) (\"%s\")",&msg,msg.c_str());
#endif
#ifndef NDEBUG
    u_int64_t t = Time::now();
#endif
    bool retv = false;
    ObjList *l = &m_handlers;
    Lock mylock(this);
    for (; l; l=l->next()) {
	MessageHandler *h = static_cast<MessageHandler*>(l->get());
	if (h && (h->null() || *h == msg)) {
	    if (h->filter() && (*(h->filter()) != msg.getValue(h->filter()->name())))
		continue;
	    unsigned int c = m_changes;
	    unsigned int p = h->priority();
	    if (trackParam() && h->trackName()) {
		NamedString* tracked = msg.getParam(trackParam());
		if (tracked)
		    tracked->append(h->trackName(),",");
		else
		    msg.addParam(trackParam(),h->trackName());
	    }
	    // mark handler as unsafe to destroy / uninstall
	    h->m_unsafe++;
	    mylock.drop();
#ifdef DEBUG
	    u_int64_t tm = Time::now();
#endif
	    retv = h->receivedInternal(msg) || retv;
#ifdef DEBUG
	    tm = Time::now() - tm;
	    if (m_warnTime && (tm > m_warnTime))
		Debug(DebugInfo,"Message '%s' [%p] passed through %p in " FMT64U " usec",
		    msg.c_str(),&msg,h,tm);
#endif
	    if (retv && !msg.broadcast())
		break;
	    mylock.acquire(this);
	    if (c == m_changes)
		continue;
	    // the handler list has changed - find again
	    NDebug(DebugAll,"Rescanning handler list for '%s' [%p] at priority %u",
		msg.c_str(),&msg,p);
	    ObjList* l2 = &m_handlers;
	    for (l = l2; l; l=l->next()) {
		MessageHandler *mh = static_cast<MessageHandler*>(l->get());
		if (!mh)
		    continue;
		if (mh == h)
		    // exact match - silently continue where we left
		    break;

		// gone past last handler priority - exit with last handler
		if ((mh->priority() > p) || ((mh->priority() == p) && (mh > h))) {
		    Debug(DebugAll,"Handler list for '%s' [%p] changed, skipping from %p (%u) to %p (%u)",
			msg.c_str(),&msg,h,p,mh,mh->priority());
		    // l will advance in the outer for loop so use previous
		    l = l2;
		    break;
		}
		l2 = l;
	    }
	    if (!l)
		break;
	}
    }
    mylock.drop();
    msg.dispatched(retv);
#ifndef NDEBUG
    t = Time::now() - t;
    if (m_warnTime && (t > m_warnTime)) {
	unsigned n = msg.length();
	String p;
	for (unsigned i = 0; i < n; i++) {
	    NamedString *s = msg.getParam(i);
	    if (s)
		p << "\n  ['" << s->name() << "']='" << *s << "'";
	}
	Debug("Performance",DebugMild,"Message %p '%s' retval '%s' returned %s in " FMT64U " usec%s",
	    &msg,msg.c_str(),msg.retValue().c_str(),retv ? "true" : "false",t,p.safe());
    }
#endif
    l = &m_hooks;
    for (; l; l=l->next()) {
	MessagePostHook *h = static_cast<MessagePostHook*>(l->get());
	if (h)
	    h->dispatched(msg,retv);
    }
    return retv;
}
Ejemplo n.º 15
0
bool MessageDispatcher::dispatch(Message& msg)
{
#ifdef XDEBUG
    Debugger debug("MessageDispatcher::dispatch","(%p) (\"%s\")",&msg,msg.c_str());
#endif
#ifndef NDEBUG
    u_int64_t t = Time::now();
#endif
    bool retv = false;
    ObjList *l = &m_handlers;
    m_mutex.lock();
    for (; l; l=l->next()) {
	MessageHandler *h = static_cast<MessageHandler*>(l->get());
	if (h && (h->null() || *h == msg)) {
	    if (h->filter() && (*(h->filter()) != msg.getValue(h->filter()->name())))
		continue;
	    unsigned int c = m_changes;
	    unsigned int p = h->priority();
	    m_mutex.unlock();
#ifdef DEBUG
	    u_int64_t tm = Time::now();
#endif
	    retv = h->received(msg);
#ifdef DEBUG
	    tm = Time::now() - tm;
	    if (m_warnTime && (tm > m_warnTime))
		Debug(DebugInfo,"Message '%s' [%p] passed through %p in " FMT64U " usec",
		    msg.c_str(),&msg,h,tm);
#endif
	    if (retv)
		break;
	    m_mutex.lock();
	    if (c == m_changes)
		continue;
	    // the handler list has changed - find again
	    NDebug(DebugAll,"Rescanning handler list for '%s' [%p] at priority %u",
		msg.c_str(),&msg,p);
	    for (l = &m_handlers; l; l=l->next()) {
		MessageHandler *mh = static_cast<MessageHandler*>(l->get());
		if (!mh)
		    continue;
		if (mh == h)
		    // exact match - silently continue where we left
		    break;

		// gone past last handler priority - exit with last handler
		if ((mh->priority() > p) || ((mh->priority() == p) && (mh > h))) {
		    Debug(DebugAll,"Handler list for '%s' [%p] changed, skipping from %p (%u) to %p (%u)",
			msg.c_str(),&msg,h,p,mh,mh->priority());
		    break;
		}
	    }
	}
    }
    if (!l)
	m_mutex.unlock();
    msg.dispatched(retv);
#ifndef NDEBUG
    t = Time::now() - t;
    if (m_warnTime && (t > m_warnTime)) {
	unsigned n = msg.length();
	String p;
	for (unsigned i = 0; i < n; i++) {
	    NamedString *s = msg.getParam(i);
	    if (s)
		p << "\n  ['" << s->name() << "']='" << *s << "'";
	}
	Debug("Performance",DebugMild,"Message %p '%s' retval '%s' returned %s in " FMT64U " usec%s",
	    &msg,msg.c_str(),msg.retValue().c_str(),retv ? "true" : "false",t,p.safe());
    }
#endif
    l = &m_hooks;
    for (; l; l=l->next()) {
	MessagePostHook *h = static_cast<MessagePostHook*>(l->get());
	if (h)
	    h->dispatched(msg,retv);
    }
    return retv;
}
Ejemplo n.º 16
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.º 17
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);
                        }
                    }
                }
            }
        }
Ejemplo n.º 18
0
void ThreadPrivate::killall()
{
    Debugger debug("ThreadPrivate::killall()");
    ThreadPrivate *t;
    bool sledgehammer = false;
    s_tmutex.lock();
    ThreadPrivate* crt = ThreadPrivate::current();
    int c = s_threads.count();
    if (crt)
	Debug(DebugNote,"Thread '%s' is soft cancelling other %d running threads",crt->m_name,c-1);
    else
	Debug(DebugNote,"Soft cancelling %d running threads",c);
    ObjList* l = &s_threads;
    while (l && (t = static_cast<ThreadPrivate *>(l->get())) != 0)
    {
	if (t != crt) {
	    Debug(DebugInfo,"Stopping ThreadPrivate '%s' [%p]",t->m_name,t);
	    t->cancel(false);
	}
	l = l->next();
    }
    for (int w = 0; w < SOFT_WAITS; w++) {
	s_tmutex.unlock();
	Thread::idle();
	s_tmutex.lock();
	c = s_threads.count();
	// ignore the current thread if we have one
	if (crt && c)
	    c--;
	if (!c) {
	    s_tmutex.unlock();
	    return;
	}
    }
    Debug(DebugMild,"Hard cancelling %d remaining threads",c);
    l = &s_threads;
    c = 1;
    while (l && (t = static_cast<ThreadPrivate *>(l->get())) != 0)
    {
	if (t == crt) {
	    l = l->next();
	    continue;
	}
	Debug(DebugInfo,"Trying to kill ThreadPrivate '%s' [%p], attempt %d",t->m_name,t,c);
	bool ok = t->cancel(true);
	if (ok) {
	    int d = 0;
	    // delay a little (exponentially) so threads have a chance to clean up
	    for (int i=1; i<=KILL_WAIT; i<<=1) {
		s_tmutex.unlock();
		Thread::msleep(i-d);
		d = i;
		s_tmutex.lock();
		if (t != l->get())
		    break;
	    }
	}
	if (t != l->get())
	    c = 1;
	else {
	    if (ok) {
#ifdef _WINDOWS
		Debug(DebugGoOn,"Could not kill %p but seems OK to delete it (library bug?)",t);
		s_tmutex.unlock();
		t->destroy();
		s_tmutex.lock();
		if (t != l->get())
		    c = 1;
#else
		Debug(DebugGoOn,"Could not kill cancelled %p so we'll abandon it (library bug?)",t);
		l->remove(t,false);
		c = 1;
#endif
		continue;
	    }
	    Thread::msleep(1);
	    if (++c >= HARD_KILLS) {
		Debug(DebugGoOn,"Could not kill %p, will use sledgehammer later.",t);
		sledgehammer = true;
		t->m_thread = 0;
		l = l->next();
		c = 1;
	    }
	}
    }
    s_tmutex.unlock();
    // last solution - a REALLY BIG tool!
    // usually too big since many libraries have threads of their own...
    if (sledgehammer) {
#ifdef THREAD_KILL
	Debug(DebugGoOn,"Brutally killing remaining threads!");
	::pthread_kill_other_threads_np();
#else
	Debug(DebugGoOn,"Aargh! I cannot kill remaining threads on this platform!");
#endif
    }
}