void SIPCall::hangup(int reason) { // Stop all RTP streams stopAllMedia(); if (not inv or not inv->dlg) { removeCall(); throw VoipLinkException("No invite session for this call"); } pjsip_route_hdr *route = inv->dlg->route_set.next; while (route and route != &inv->dlg->route_set) { char buf[1024]; int printed = pjsip_hdr_print_on(route, buf, sizeof(buf)); if (printed >= 0) { buf[printed] = '\0'; RING_DBG("[call:%s] Route header %s", getCallId().c_str(), buf); } route = route->next; } const int status = reason ? reason : inv->state <= PJSIP_INV_STATE_EARLY and inv->role != PJSIP_ROLE_UAC ? PJSIP_SC_CALL_TSX_DOES_NOT_EXIST : inv->state >= PJSIP_INV_STATE_DISCONNECTED ? PJSIP_SC_DECLINE : 0; // Notify the peer terminateSipSession(status); setState(Call::ConnectionState::DISCONNECTED, reason); removeCall(); }
// must be write-locked, SessionManager must be read-locked void CallManager::EndCall(Connection *sqlCon, unsigned int call_id) { Call *call = getCall(call_id); if (!call) return; call->lock(); //call->sendCallStatuses(); if (call->tarificate(sqlCon)) { log(LOG_FATAL, "Error tarficating call[%d].", call_id); } call->DBwrite(sqlCon); if (call->getState() == ACTIVE || call->getState() == END) { if (User::CheckNeedMark(sqlCon, call->getClient(), call->getTranslator())) { Session *cs = sManager->findSessionByUser(call->getClient()); if (cs) { struct timeval tv; gettimeofday(&tv, 0); unsigned long time = tv.tv_sec*1000 + tv.tv_usec/1000; cs->sendPacket_MarkRequest(call->getTranslator(), call->getTranslatorName(), time); } } } call->unlock(); log(LOG_VERBOSE, "EndCall[%d->%d]: accounted=%d cost=%d.", call->getClient(), call->getTranslator(), call->getAccountedTime(), call->getCost()); removeCall(call_id); delete call; }
void SIPCall::onClosed() { Manager::instance().peerHungupCall(*this); removeCall(); Manager::instance().checkAudio(); }
void SIPCall::onFailure(signed cause) { setState(CallState::MERROR, ConnectionState::DISCONNECTED, cause); Manager::instance().callFailure(*this); removeCall(); }
/** * * @brief removes all call transitions to or from the given state * * @param - state: the state whose transitions to remove * @return false if no transitions were removed, true otherwise * */ bool TransitionStorage::removeCallTransWith( State state ) { Calls outgoing = T_info.callTrans(state); Calls incoming = T_info.entryTrans(state); //Remove the transitions. for( CallIterator rit = outgoing.begin(); rit != outgoing.end(); rit++ ) { removeCall(*rit); } //Remove the transitions. for( CallIterator rit = incoming.begin(); rit != incoming.end(); rit++ ) { removeCall(*rit); } return (outgoing.size() > 0) || (incoming.size() > 0); }
void Server::broadcastMessage(QString message) { qlonglong id = invokeOnPeer("broadcastMessageSlot", message); if(id){ NoronRemoteCallBase *call = new NoronRemoteCallBase(NoronRemoteCallBase::EventLoop); addCall(id, call); call->eventLoop->exec(); removeCall(id); delete call; } }
void IAXVoIPLink::iaxHandlePrecallEvent(iax_event* event) { IAXCall *call; std::string id; int format; switch (event->etype) { case IAX_EVENT_CONNECT: id = Manager::instance().getNewCallID(); call = new IAXCall(id, Call::INCOMING); call->session = event->session; call->setConnectionState(Call::PROGRESSING); if (event->ies.calling_number) call->setPeerNumber(event->ies.calling_number); if (event->ies.calling_name) call->setDisplayName(std::string(event->ies.calling_name)); // if peerNumber exist append it to the name string call->initRecFilename(std::string(event->ies.calling_number)); Manager::instance().incomingCall(*call, accountID_); format = call->getFirstMatchingFormat(event->ies.format, accountID_); if (!format) format = call->getFirstMatchingFormat(event->ies.capability, accountID_); iax_accept(event->session, format); iax_ring_announce(event->session); addCall(call); call->format = format; break; case IAX_EVENT_HANGUP: id = iaxFindCallBySession(event->session)->getCallId(); Manager::instance().peerHungupCall(id); removeCall(id); break; case IAX_EVENT_TIMEOUT: // timeout for an unknown session case IAX_IE_MSGCOUNT: case IAX_EVENT_REGACK: case IAX_EVENT_REGREJ: case IAX_EVENT_REGREQ: // Received when someone wants to register to us!?! // Asterisk receives and answers to that, not us, we're a phone. default: break; } }
void Server::userLeaved(QString username) { qlonglong id = invokeOnPeer("userLeavedSlot", username); if(id){ NoronRemoteCallBase *call = new NoronRemoteCallBase(NoronRemoteCallBase::EventLoop); addCall(id, call); call->eventLoop->exec(); removeCall(id); delete call; } }
void Server::imageSent(QString username, QPixmap image) { qlonglong id = invokeOnPeer("imageSentSlot", username,image); if(id){ NoronRemoteCallBase *call = new NoronRemoteCallBase(NoronRemoteCallBase::EventLoop); addCall(id, call); call->eventLoop->exec(); removeCall(id); delete call; } }
void IAXVoIPLink::refuse(const std::string& id) { IAXCall* call = getIAXCall(id); if (call) { mutexIAX_.enter(); iax_reject(call->session, (char*) "Call rejected manually."); mutexIAX_.leave(); removeCall(id); } }
void IAXVoIPLink::peerHungup(const std::string& id) { IAXCall* call = getIAXCall(id); if (call == NULL) throw VoipLinkException("Could not find call"); Manager::instance().getMainBuffer()->unBindAll(call->getCallId()); call->session = NULL; removeCall(id); }
void SIPCall::refuse() { if (!isIncoming() or getConnectionState() == ConnectionState::CONNECTED or !inv) return; stopAllMedia(); // Notify the peer terminateSipSession(PJSIP_SC_DECLINE); setState(Call::ConnectionState::DISCONNECTED, ECONNABORTED); removeCall(); }
int Client::getRandomNumber() { qlonglong id = invokeOnPeer("getRandomNumberSlot"); if(id){ NoronRemoteCallBase *call = new NoronRemoteCallBase(NoronRemoteCallBase::EventLoop); addCall(id, call); call->eventLoop->exec(); int ret = call->returnData.value<int>(); removeCall(id); delete call; return ret; } }
void IAXVoIPLink::hangup(const std::string& id) { IAXCall* call = getIAXCall(id); if (call == NULL) throw VoipLinkException("Could not find call"); Manager::instance().getMainBuffer()->unBindAll(call->getCallId()); mutexIAX_.enter(); iax_hangup(call->session, (char*) "Dumped Call"); mutexIAX_.leave(); call->session = NULL; removeCall(id); }
/** * * @brief removes all call transitions with the given symbol * * @param - sym: the symbol whose transitions to remove * @return false if no transitions were removed, true otherwise * */ bool TransitionStorage::removeCallTransSym( Symbol sym ) { Calls removeTrans; //Find transitions to remove. for( CallIterator cit = callTrans.begin(); cit != callTrans.end(); cit++ ) { if( getCallSym(*cit) == sym ) removeTrans.insert(*cit); } //Remove transitions. for( CallIterator rit = removeTrans.begin(); rit != removeTrans.end(); rit++ ) { removeCall(*rit); } return removeTrans.size() > 0; }
void JingleVoiceCaller::receiveStanza(const QString& stanza) { QDomDocument doc; doc.setContent(stanza); // Check if it is offline presence from an open chat if (doc.documentElement().tagName() == "presence") { Jid from = Jid(doc.documentElement().attribute("from")); QString type = doc.documentElement().attribute("type"); if (type == "unavailable" && calls_.contains(from.full())) { qDebug("JingleVoiceCaller: User went offline without closing a call."); removeCall(from); emit terminated(from); } return; } // Check if the packet is destined for libjingle. // We could use Session::IsClientStanza to check this, but this one crashes // for some reason. QDomNode n = doc.documentElement().firstChild(); bool ok = false; while (!n.isNull() && !ok) { QDomElement e = n.toElement(); if (!e.isNull() && e.attribute("xmlns") == JINGLE_NS) { ok = true; } n = n.nextSibling(); } // Spread the word if (ok) { qDebug(QString("jinglevoicecaller.cpp: Handing down %1").arg(stanza)); buzz::XmlElement *e = buzz::XmlElement::ForStr(stanza.ascii()); phone_client_->OnIncomingStanza(e); } }
void IAXVoIPLink::iaxHandleCallEvent(iax_event* event, IAXCall* call) { std::string id = call->getCallId(); switch (event->etype) { case IAX_EVENT_HANGUP: Manager::instance().peerHungupCall(id); removeCall(id); break; case IAX_EVENT_REJECT: call->setConnectionState(Call::CONNECTED); call->setState(Call::ERROR); Manager::instance().callFailure(id); removeCall(id); break; case IAX_EVENT_ACCEPT: if (event->ies.format) call->format = event->ies.format; break; case IAX_EVENT_ANSWER: case IAX_EVENT_TRANSFER: if (call->getConnectionState() == Call::CONNECTED) break; Manager::instance().addStream(call->getCallId()); call->setConnectionState(Call::CONNECTED); call->setState(Call::ACTIVE); if (event->ies.format) call->format = event->ies.format; Manager::instance().peerAnsweredCall(id); Manager::instance().getAudioDriver()->startStream(); Manager::instance().getMainBuffer()->flushAllBuffers(); break; case IAX_EVENT_BUSY: call->setConnectionState(Call::CONNECTED); call->setState(Call::BUSY); Manager::instance().callBusy(id); removeCall(id); break; case IAX_EVENT_VOICE: iaxHandleVoiceEvent(event, call); break; case IAX_EVENT_TEXT: Manager::instance().incomingMessage(call->getCallId(), call->getPeerNumber(), std::string((const char*) event->data)); break; case IAX_EVENT_RINGA: call->setConnectionState(Call::RINGING); Manager::instance().peerRingingCall(call->getCallId()); break; case IAX_IE_MSGCOUNT: case IAX_EVENT_TIMEOUT: case IAX_EVENT_PONG: default: break; case IAX_EVENT_URL: if (Manager::instance().getConfigString("Hooks", "Hooks.iax2_enabled") == "1") UrlHook::runAction(Manager::instance().getConfigString("Hooks", "Hooks.url_command"), (char*) event->data); break; } }
/** * * @brief remove a call transition from the NWA * * @param - from: the state the edge departs from * @param - sym: the symbol labeling the edge * @param - to: the state the edge arrives to * @return false if the call transition does not exist in the NWA * */ bool TransitionStorage::removeCall( State from, Symbol sym, State to ) { Call ct(from,sym,to); return removeCall(ct); }