All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.lastbamboo.common.sip.client.SipClientMessageVisitor Maven / Gradle / Ivy

The newest version!
package org.lastbamboo.common.sip.client;

import java.net.InetSocketAddress;

import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.math.RandomUtils;
import org.lastbamboo.common.offer.answer.AnswererOfferAnswerListener;
import org.lastbamboo.common.offer.answer.OfferAnswer;
import org.lastbamboo.common.offer.answer.OfferAnswerConnectException;
import org.lastbamboo.common.offer.answer.OfferAnswerFactory;
import org.lastbamboo.common.sip.stack.message.DoubleCrlfKeepAlive;
import org.lastbamboo.common.sip.stack.message.Invite;
import org.lastbamboo.common.sip.stack.message.Register;
import org.lastbamboo.common.sip.stack.message.RequestTimeoutResponse;
import org.lastbamboo.common.sip.stack.message.SipMessage;
import org.lastbamboo.common.sip.stack.message.SipMessageVisitor;
import org.lastbamboo.common.sip.stack.message.SipResponse;
import org.lastbamboo.common.sip.stack.message.UnknownSipRequest;
import org.lastbamboo.common.sip.stack.message.header.SipHeaderNames;
import org.lastbamboo.common.sip.stack.transaction.client.SipClientTransaction;
import org.lastbamboo.common.sip.stack.transaction.client.SipTransactionTracker;
import org.littleshoot.mina.common.ByteBuffer;
import org.littleshoot.util.SessionSocketListener;
import org.littleshoot.util.mina.MinaUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Class that visits incoming SIP messages for SIP clients.
 */
public class SipClientMessageVisitor implements SipMessageVisitor {

    private final Logger m_log = LoggerFactory.getLogger(getClass());
    private final SipTransactionTracker m_transactionTracker;
    private final SipClient m_sipClient;
    private final OfferAnswerFactory m_offerAnswerFactory;
    private final SessionSocketListener callListener;
    private final InetSocketAddress serverAddress;

    /**
     * Visitor for message received on SIP clients.
     * 
     * @param sipClient The SIP client for writing any necessary messages.
     * @param tracker The tracker for looking up the corresponding transactions 
     * for received messages.
     * @param offerAnswerFactory Class that processes incoming INVITEs.
     * @param serverAddress The listener for incoming sockets on the answerer.
     */
    public SipClientMessageVisitor(final SipClient sipClient,
            final SipTransactionTracker tracker,
            final OfferAnswerFactory offerAnswerFactory,
            final InetSocketAddress serverAddress,
            final SessionSocketListener callListener) {
        this.m_sipClient = sipClient;
        this.m_transactionTracker = tracker;
        this.m_offerAnswerFactory = offerAnswerFactory;
        this.serverAddress = serverAddress;
        this.callListener = callListener;
    }

    public void visitRequestTimedOut(final RequestTimeoutResponse response) {
        m_log.debug("Visiting request timed out response: " + response);
        notifyTransaction(response);
    }

    public void visitInvite(final Invite invite) {
        m_log.debug("Received invite: {}", invite);

        final ByteBuffer offer = invite.getBody();
        final String offerString = MinaUtils.toAsciiString(offer);

        final String from = invite.getHeader(SipHeaderNames.FROM).toString();
        
        final String rawFrom = StringUtils.substringBetween(from, "<", ">");
        final String toUse;
        if (StringUtils.isBlank(rawFrom)) {
            toUse = from;
        } else {
            toUse = rawFrom;
        }
        final String id = toUse + "-"+RandomUtils.nextInt();
        
        // Process the invite.
        final OfferAnswer offerAnswer;
        try {
            // offerAnswer = this.m_offerAnswerFactory.createAnswerer(
            // this.m_offerAnswerListener);
            offerAnswer = 
                this.m_offerAnswerFactory.createAnswerer(
                    new AnswererOfferAnswerListener(id, 
                        this.serverAddress, this.callListener, offerString), 
                        true);
        } catch (final OfferAnswerConnectException e) {
            // This indicates we could not establish the necessary connections
            // for generating our candidates.
            m_log.warn("We could not create candidates for offer: " + 
                offerString, e);
            // Generate a SIP error response.
            // See http://tools.ietf.org/html/rfc3261#section-13.3.1.3
            this.m_sipClient.writeInviteRejected(invite, 488,
                    "Not Acceptable Here");
            return;
        }
        final byte[] answer = offerAnswer.generateAnswer();
        this.m_sipClient.writeInviteOk(invite, ByteBuffer.wrap(answer));
        offerAnswer.processOffer(offer);// , this.m_offerAnswerListener);

        m_log.debug("Done processing INVITE!!!");
    }

    public void visitRegister(final Register register) {
        // Should never happen on UAS.
        m_log.error("Got REGISTER request on UAS -- weird: " + register);
    }

    public void visitDoubleCrlfKeepAlive(final DoubleCrlfKeepAlive keepAlive) {
        // Should never happen on UAS.
        m_log.error("Got keep-alive request on UAS -- weird: ");
    }

    public void visitUnknownRequest(final UnknownSipRequest request) {
        m_log.error("Unknown request on UAS: " + request);
    }

    public void visitResponse(final SipResponse response) {
        // Identify the transaction for this response and the corresponding
        // session it creates.
        m_log.debug("Visiting OK response: " + response);
        notifyTransaction(response);
    }

    private void notifyTransaction(final SipMessage response) {
        final SipClientTransaction ct = this.m_transactionTracker
                .getClientTransaction(response);
        m_log.debug("Accessed transaction: " + ct);

        if (ct == null) {
            m_log.warn("No matching transaction for response: " + response);
            return;
        }

        response.accept(ct);
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy