void ThreadPrivate::pubdestroy() { #ifdef DEBUG Debugger debug(DebugAll,"ThreadPrivate::pubdestroy()"," %p '%s' [%p]",m_thread,m_name,this); #endif m_updest = false; cleanup(); m_thread = 0; if (current() == this) { cancel(true); // should never reach here... Debug(DebugFail,"ThreadPrivate::pubdestroy() past cancel??? [%p]",this); } else { cancel(false); // delay a little so thread has a chance to clean up for (int i=0; i<20; i++) { s_tmutex.lock(); bool done = !s_threads.find(this); s_tmutex.unlock(); if (done) return; Thread::idle(false); } if (m_cancel && !cancel(true)) Debug(DebugWarn,"ThreadPrivate::pubdestroy() %p '%s' failed cancel [%p]",m_thread,m_name,this); } }
// 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; }
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); }
// 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"); } }
// 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); } } } } }