// Update members with data taken from a SDP, return true if something changed bool SDPMedia::update(const char* formats, int rport, int lport, bool force) { DDebug(DebugAll,"SDPMedia::update('%s',%d,%d,%s) [%p]", formats,rport,lport,String::boolText(force),this); bool chg = false; String tmp(formats); if (tmp && (m_formats != tmp)) { if (tmp.find(',') < 0) { // single format received, check if acceptable if (m_formats && !force && m_formats.find(tmp) < 0) { Debug(DebugNote,"Not changing to '%s' from '%s' [%p]", formats,m_formats.c_str(),this); tmp.clear(); } } else if (m_formats && !force) { // from received list keep only already offered formats ObjList* l1 = tmp.split(',',false); ObjList* l2 = m_formats.split(',',false); for (ObjList* fmt = l1->skipNull(); fmt; ) { if (l2->find(fmt->get()->toString())) fmt = fmt->skipNext(); else { fmt->remove(); fmt = fmt->skipNull(); } } tmp.clear(); tmp.append(l1,","); TelEngine::destruct(l1); TelEngine::destruct(l2); if (tmp.null()) Debug(DebugNote,"Not changing formats '%s' [%p]",m_formats.c_str(),this); } if (tmp && (m_formats != tmp)) { chg = true; m_formats = tmp; int q = m_formats.find(','); m_format = m_formats.substr(0,q); Debug(DebugInfo,"Choosing offered '%s' format '%s' [%p]", c_str(),m_format.c_str(),this); } } if (rport >= 0) { tmp = rport; if (m_rPort != tmp) { chg = true; m_rPort = tmp; } } if (lport >= 0) { tmp = lport; if (m_lPort != tmp) { m_localChanged = true; chg = true; m_lPort = tmp; } } return chg; }
unsigned int ObjVector::assign(ObjList& list, bool move, unsigned int maxLen) { if (!maxLen) maxLen = list.count(); clear(); if (maxLen) { m_objects = new GenObject*[maxLen]; ObjList* l = list.skipNull(); for (unsigned int i = 0; i < maxLen; i++) { if (l) { if (move) { m_objects[i] = l->remove(false); l = l->skipNull(); } else { m_objects[i] = l->get(); l = l->skipNext(); } } else m_objects[i] = 0; } m_length = maxLen; } return maxLen; }
GenObject* HashList::remove(GenObject* obj, bool delobj, bool useHash) { ObjList* n = 0; if (useHash && obj) n = find(obj,obj->toString().hash()); else n = find(obj); return n ? n->remove(delobj) : 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)); }
// Remove a specific parameter NamedList& NamedList::clearParam(NamedString* param, bool delParam) { if (!param) return *this; ObjList* o = m_params.find(param); if (o) o->remove(delParam); XDebug(DebugInfo,"NamedList::clearParam(%p) found=%p",param,o); return *this; }
MrcpConnection::~MrcpConnection() { s_mutex.lock(); s_conns.remove(this,false); s_mutex.unlock(); if (m_socket) { m_socket->terminate(); delete m_socket; m_socket = 0; } }
ThreadPrivate::~ThreadPrivate() { #ifdef DEBUG Debugger debug("ThreadPrivate::~ThreadPrivate()"," %p '%s' [%p]",m_thread,m_name,this); #endif m_running = false; Lock lock(s_tmutex); s_threads.remove(this,false); if (m_thread && m_updest) { Thread *t = m_thread; m_thread = 0; // let other threads access the list while we delete our upper layer lock.drop(); delete t; } }
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; }
// 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; }
GenObject* ObjList::remove(GenObject* obj, bool delobj) { ObjList *n = find(obj); return n ? n->remove(delobj) : 0; }
// 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); }
GenObject* ObjList::remove(const String& str, bool delobj) { ObjList *n = find(str); return n ? n->remove(delobj) : 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 } }