예제 #1
0
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();
}
예제 #2
0
// 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;
}
예제 #3
0
void
SIPCall::onClosed()
{
    Manager::instance().peerHungupCall(*this);
    removeCall();
    Manager::instance().checkAudio();
}
예제 #4
0
void
SIPCall::onFailure(signed cause)
{
    setState(CallState::MERROR, ConnectionState::DISCONNECTED, cause);
    Manager::instance().callFailure(*this);
    removeCall();
}
예제 #5
0
    /** 
     *
     * @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);
    }
예제 #6
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;
    }
}
예제 #7
0
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;
    }
}
예제 #8
0
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;
    }
}
예제 #9
0
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;
    }
}
예제 #10
0
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);
    }
}
예제 #11
0
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);
}
예제 #12
0
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();
}
예제 #13
0
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;
    }
    
}
예제 #14
0
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);
}
예제 #15
0
    /** 
     *
     * @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;  
    }
예제 #16
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);
	}
}
예제 #17
0
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;
    }
}
예제 #18
0
 /**
  *
  * @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);
 }