SIPEvent* SIPEngine::getEvent() { Lock lock(this); ObjList* l = m_transList.skipNull(); if (!l) return 0; u_int64_t time = Time::now(); for (; l; l = l->skipNext()) { SIPTransaction* t = static_cast<SIPTransaction*>(l->get()); SIPEvent* e = t->getEvent(true,time); if (e) { DDebug(this,DebugInfo,"Got pending event %p (state %s) from transaction %p [%p]", e,SIPTransaction::stateName(e->getState()),t,this); if (t->getState() == SIPTransaction::Invalid) m_transList.remove(t); return e; } } time = Time::now(); for (l = m_transList.skipNull(); l; l = l->skipNext()) { SIPTransaction* t = static_cast<SIPTransaction*>(l->get()); SIPEvent* e = t->getEvent(false,time); if (e) { DDebug(this,DebugInfo,"Got event %p (state %s) from transaction %p [%p]", e,SIPTransaction::stateName(e->getState()),t,this); if (t->getState() == SIPTransaction::Invalid) m_transList.remove(t); return e; } } return 0; }
void ListIterator::assign(HashList& list, int offset) { clear(); m_hashList = &list; m_length = list.count(); if (!m_length) return; m_objects = new GenObject* [m_length]; m_hashes = new unsigned int[m_length]; offset = (m_length - offset) % m_length; unsigned int i = 0; for (unsigned int n = 0; n < list.length(); n++) { ObjList* l = list.getList(n); if (!l) continue; for (l = l->skipNull(); i < m_length; l = l->skipNext()) { if (!l) break; unsigned int idx = ((i++) + offset) % m_length; m_objects[idx] = l->get(); m_hashes[idx] = l->get()->toString().hash(); } } while (i < m_length) m_objects[((i++) + offset) % m_length] = 0; }
// Convert this message to a string representation void MGCPMessage::toString(String& dest) const { // Construct first line dest << name() << " " << transactionId(); if (isCommand()) dest << " " << endpointId() << " " << m_version; else if (m_comment) dest << " " << m_comment; dest << "\r\n"; // Append message parameters unsigned int n = params.count(); for (unsigned int i = 0; i < n; i++) { NamedString* ns = params.getParam(i); if (!ns) continue; dest << ns->name() << ": " << *ns << "\r\n"; } // Append SDP(s) for (ObjList* obj = sdp.skipNull(); obj; obj = obj->skipNext()) { String s; MimeSdpBody* tmp = static_cast<MimeSdpBody*>(obj->get()); for (ObjList* o = tmp->lines().skipNull(); o; o = o->skipNext()) { NamedString* ns = static_cast<NamedString*>(o->get()); if (*ns) s << ns->name() << "=" << *ns << "\r\n"; } if (s) dest << "\r\n" << s; } }
// 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; }
// Utility: print the result of dns query // Return the code static int printResult(int type, int code, const char* dname, ObjList& result, String* error) { #ifdef DEBUG if (!code) { String s; int crt = 0; for (ObjList* o = result.skipNull(); o; o = o->skipNext()) { DnsRecord* rec = static_cast<DnsRecord*>(o->get()); if (!s) s << "\r\n-----"; s << "\r\n" << ++crt << ":"; rec->dump(s); } if (s) s << "\r\n-----"; Debug(DebugAll,"%s query for '%s' got %d records%s", lookup(type,Resolver::s_types),dname,result.count(),s.safe()); } else { String dummy; if (!error) { error = &dummy; #ifdef _WINDOWS Thread::errorString(dummy,code); #elif defined(__NAMESER) dummy = hstrerror(code); #endif } Debug(DebugNote,"%s query for '%s' failed with code %d error=%s", lookup(type,Resolver::s_types),dname,code,TelEngine::c_safe(error)); } #endif return code; }
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; }
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; }
String ExpEvaluator::dump() const { String res; for (ObjList* l = m_opcodes.skipNull(); l; l = l->skipNext()) { const ExpOperation* o = static_cast<const ExpOperation*>(l->get()); const char* oper = getOperator(o->opcode()); if (oper) { res << " " << oper; continue; } switch (o->opcode()) { case OpcPush: if (o->number()) res << " " << (int)o->number(); else res << " '" << *o << "'"; break; case OpcField: res << " " << o->name(); break; case OpcFunc: res << " " << o->name() << "(" << (int)o->number() << ")"; break; default: res << " [" << o->opcode() << "]"; } } return res; }
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; }
// 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; }
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); }
// 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())); } }
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); } }
ExpEvaluator::ExpEvaluator(const ExpEvaluator& original) : m_operators(original.m_operators), m_extender(0) { extender(original.extender()); for (ObjList* l = original.m_opcodes.skipNull(); l; l = l->skipNext()) { const ExpOperation* o = static_cast<const ExpOperation*>(l->get()); m_opcodes.append(new ExpOperation(*o)); } }
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(); }
ExpOperation* ExpEvaluator::popOne(ObjList& stack) { GenObject* o = 0; for (ObjList* l = stack.skipNull(); l; l=l->skipNext()) o = l->get(); stack.remove(o,false); DDebug(DebugInfo,"Popped: %p",o); return static_cast<ExpOperation*>(o); }
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)); }
ExpEvaluator::ExpEvaluator(const ExpEvaluator& original) : m_operators(original.m_operators), m_unaryOps(original.unaryOps()), m_inError(false), m_lineNo(original.lineNumber()), m_extender(0) { extender(original.extender()); for (ObjList* l = original.m_opcodes.skipNull(); l; l = l->skipNext()) { const ExpOperation* o = static_cast<const ExpOperation*>(l->get()); m_opcodes.append(o->clone()); } }
bool ExpEvaluator::runEvaluate(ObjList& stack) const { DDebug(DebugInfo,"runEvaluate(%p)",&stack); for (ObjList* l = m_opcodes.skipNull(); l; l = l->skipNext()) { const ExpOperation* o = static_cast<const ExpOperation*>(l->get()); if (!runOperation(stack,*o)) return false; } return true; }
CallInfo* CallList::find(const CallEndpoint* call) { ObjList* l = m_calls.skipNull(); for (; l; l = l->skipNext()) { CallInfo* info = static_cast<CallInfo*>(l->get()); if (info->call() == call) return info; } return 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(); }
// Find the info object associated with a remote peer by alias name MGCPEpInfo* MGCPEndpoint::findAlias(const String& alias) { if (alias.null()) return 0; Lock lock(this); for (ObjList* o = m_remote.skipNull(); o; o = o->skipNext()) { MGCPEpInfo* info = static_cast<MGCPEpInfo*>(o->get()); if (alias == info->alias) return info; } return 0; }
void CallEndpoint::destroyed() { #ifdef DEBUG ObjList* l = m_data.skipNull(); for (; l; l=l->skipNext()) { DataEndpoint* e = static_cast<DataEndpoint*>(l->get()); Debug(DebugAll,"Endpoint at %p type '%s' refcount=%d",e,e->name().c_str(),e->refcount()); } #endif disconnect(true,0,true); m_data.clear(); }
// Try to start RTP for all media bool SDPSession::startRtp(RefObject* context) { if (m_rtpForward || !m_rtpMedia || (m_mediaStatus != MediaStarted)) return false; DDebug(m_parser,DebugAll,"SDPSession::startRtp(%p) [%p]",context,this); bool ok = false; for (ObjList* o = m_rtpMedia->skipNull(); o; o = o->skipNext()) { SDPMedia* m = static_cast<SDPMedia*>(o->get()); ok = dispatchRtp(m,m_rtpAddr,true,false,context) || ok; } return ok; }
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()); }
bool TableEvaluator::evalWhere() { if (m_where.null()) return true; ObjList res; if (!m_where.evaluate(res)) return false; ObjList* first = res.skipNull(); if (!first) return false; const ExpOperation* o = static_cast<const ExpOperation*>(first->get()); return (o->opcode() == ExpEvaluator::OpcPush) && o->number(); }
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; }
bool CallEndpoint::connect(CallEndpoint* peer, const char* reason, bool notify) { if (!peer) { disconnect(reason,notify); return false; } if (peer == m_peer) return true; if (peer == this) { Debug(DebugWarn,"CallEndpoint '%s' trying to connect to itself! [%p]",m_id.c_str(),this); return false; } DDebug(DebugAll,"CallEndpoint '%s' connecting peer %p to [%p]",m_id.c_str(),peer,this); #if 0 if (!s_mutex.lock(5000000)) { Debug(DebugFail,"Call connect failed - deadlock on call endpoint mutex!"); Engine::restart(0); return false; } #endif // are we already dead? if (!ref()) return false; disconnect(reason,notify); // is our intended peer dead? if (!peer->ref()) { deref(); return false; } peer->disconnect(reason,notify); ObjList* l = m_data.skipNull(); for (; l; l=l->skipNext()) { DataEndpoint* e = static_cast<DataEndpoint*>(l->get()); e->connect(peer->getEndpoint(e->name())); } m_peer = peer; peer->setPeer(this,reason,notify); connected(reason); #if 0 s_mutex.unlock(); #endif return true; }
ObjList* ObjList::append(const GenObject* obj, bool compact) { #ifdef XDEBUG Debugger debug("ObjList::append","(%p,%d) [%p]",obj,compact,this); #endif ObjList *n = last(); if (n->get() || !compact) { n->m_next = new ObjList(); n = n->m_next; } else n->m_delete = true; n->set(obj); return n; }
void ExpEvaluator::addOpcode(ExpEvaluator::Opcode oper) { DDebug(DebugAll,"addOpcode %u",oper); if (oper == OpcAs) { // the second operand is used just for the field name ExpOperation* o = 0; for (ObjList* l = m_opcodes.skipNull(); l; l=l->skipNext()) o = static_cast<ExpOperation*>(l->get()); if (o && (o->opcode() == OpcField)) { o->m_opcode = OpcPush; o->String::operator=(o->name()); } } m_opcodes.append(new ExpOperation(oper)); }