无法建立SIP会话(jain-sip)

时间:2017-05-12 11:49:13

标签: java sip sdp jain-sip

我正在使用Jain Sip,我的用例是这样的: 一个注册商,一个呼叫者和一个被呼叫者。 Caller和Callee在注册商处注册。然后呼叫者发起呼叫。 Invite到达我的被叫方但是当我尝试发送“RINGING”响应时,它无法到达我的来电者。

注册官:172.18.18.109:5060

来电者:172.18.18.52:5066

Callee:172.18.18.52:5067

enter image description here

这是我的代码:

呼叫者:

import mypackage.voip.model.ClientStatus;
import gov.nist.javax.sip.address.AddressFactoryImpl;
import gov.nist.javax.sip.header.HeaderFactoryImpl;
import gov.nist.javax.sip.message.MessageFactoryImpl;
import javax.sdp.*;
import javax.sip.*;
import javax.sip.address.Address;
import javax.sip.address.SipURI;
import javax.sip.header.*;
import javax.sip.message.Request;
import javax.sip.message.Response;
import java.text.ParseException;
import java.util.*;

import static mypackage.voip.model.ClientStatus.*;

public class Caller implements SipListener {
    private String myIpAddress = "172.18.18.52";
    private String registrarIp = "172.18.18.109";
    private int myPort = 5066;
    private String myTransportProtocol = "UDP";
    private String myUserName = "caller";
    private String viaHostName = registrarIp;
    private int viaHostPort = 5060;
    private AddressFactoryImpl addressFactory;
    private SipStack sipStack;
    private SipProvider sipProvider = null;
    private MessageFactoryImpl messageFactory;
    private HeaderFactoryImpl headerFactory;
    private ClientStatus clientStatus = DISCONNECTED;
    private String myDomainName = "172.18.18.52";
    private String viaHostBranch = "abcdefghi";

    public Caller(String name, String ipAddress, int port, String protocol) {
        this.myUserName = name;
        this.myTransportProtocol = protocol;
        this.myIpAddress = ipAddress;
        this.myPort = port;
        changeClientStatusTo(DISCONNECTED);
    }

    public void init() throws PeerUnavailableException, TooManyListenersException {
        SipFactory sipFactory = SipFactory.getInstance();
        Properties properties = new Properties();
        properties.setProperty("javax.sip.STACK_NAME", myIpAddress + ":" + myPort);
        sipStack = sipFactory.createSipStack(properties);
        addressFactory = new AddressFactoryImpl();
        messageFactory = new MessageFactoryImpl();
        headerFactory = new HeaderFactoryImpl();
        sipProvider = getSipProvider();

    }

    public void doRegistration(String registrarIp) throws ParseException, InvalidArgumentException {
        if (startRegistration(registrarIp)) {
            changeClientStatusTo(REGISTERING);
        }
    }
    private SipProvider getSipProvider() {
        try {
            ListeningPoint listeningPoint = sipStack.createListeningPoint(myIpAddress, myPort, myTransportProtocol);

            if (sipProvider != null)
                return sipProvider;
            sipProvider = sipStack.createSipProvider(listeningPoint);
            sipProvider.addSipListener(this);
            return sipProvider;
        } catch (Exception ex) {
            ex.printStackTrace();
            return null;
        }
    }

    private void changeClientStatusTo(ClientStatus newClientStatus) {
        this.clientStatus = newClientStatus;
    }
    public Address getMyContactAddress() {
        return createAddress(myUserName, myIpAddress, myPort);
    }
    private Address createAddress(String username, String hostname, int port) {
        try {
            return addressFactory.createAddress(String.format("%s <sip:%s@%s:%s;transport=%s>",
                    username,
                    username,
                    hostname,
                    port,
                    myTransportProtocol));
        } catch (ParseException e) {
            e.printStackTrace();
            return null;
        }
    }
    private boolean startRegistration(String registrarIpAddress) throws ParseException, InvalidArgumentException {
        SipURI requestURI = addressFactory.createSipURI("sip:" + registrarIpAddress + ":5060");

        CallIdHeader callIdHeader = headerFactory.createCallIdHeader("callID");
        CSeqHeader cSeqHeader = headerFactory.createCSeqHeader(2L, Request.REGISTER);

        ContactHeader contactHeader = headerFactory.createContactHeader(getMyContactAddress());
        ExpiresHeader expiresHeader = headerFactory.createExpiresHeader(217);

        Address fromAddress = getMyContactAddress();
        Address toAddress = fromAddress;

        FromHeader fromHeader = headerFactory.createFromHeader(fromAddress, "tag");
        ToHeader toHeader = headerFactory.createToHeader(toAddress, "tag");

        List viaHeaders = Arrays.asList();
        MaxForwardsHeader maxForwards = headerFactory.createMaxForwardsHeader(70);
        Request register = messageFactory.createRequest(requestURI,
                Request.REGISTER,
                callIdHeader,
                cSeqHeader,
                fromHeader,
                toHeader,
                viaHeaders,
                maxForwards);
        register.addHeader(contactHeader);
        register.addHeader(expiresHeader);
        return sendRequest(register);
    }

    private boolean sendRequest(Request request) {
        sipProvider = getSipProvider();
        try {
            ClientTransaction clientTransaction = sipProvider.getNewClientTransaction(request);
            clientTransaction.sendRequest();
            return true;
        } catch (SipException e) {
            e.printStackTrace();
        }
        return false;
    }



    private boolean sendInvite(Address addressToInvite) throws SdpException {
        try {
            CallIdHeader callIdHeader = headerFactory.createCallIdHeader("callID");
            CSeqHeader cSeqHeader = headerFactory.createCSeqHeader(System.currentTimeMillis() / 1000L, Request.INVITE);

            Address fromAddress = getMySipAddress();
            FromHeader fromHeader = headerFactory.createFromHeader(fromAddress, "meinTag");
            ToHeader toHeader = headerFactory.createToHeader(addressToInvite, null);

            ViaHeader viaHeader = headerFactory.createViaHeader(viaHostName,
                    viaHostPort,
                    myTransportProtocol,
                    viaHostBranch);
            List viaHeaders = Arrays.asList(viaHeader);

            Address sipAd = addressFactory.createAddress("sip:" + toHeader.getAddress().getDisplayName() + "@" + registrarIp);
            MaxForwardsHeader maxForwards = headerFactory.createMaxForwardsHeader(70);
            Request invite = messageFactory.createRequest(sipAd.getURI(),
                    Request.INVITE,
                    callIdHeader,
                    cSeqHeader,
                    fromHeader,
                    toHeader,
                    viaHeaders,
                    maxForwards);

            AllowHeader allowHeader = headerFactory.createAllowHeader("PRACK, INVITE, ACK, BYE, CANCEL, UPDATE, INFO, SUBSCRIBE, NOTIFY, REFER, MESSAGE, OPTIONS");
            invite.addHeader(allowHeader);

            ContactHeader contactHeader = headerFactory.createContactHeader(toHeader.getAddress());
            invite.addHeader(contactHeader);

            SessionDescription sessionDescription = SdpFactory.getInstance().createSessionDescription();
            String sdpData =
                    "v=0\n" +
                            "o=Lautsprecher 13760799956958020 13760799956958020 IN IP4 172.18.18.52\n" +
                            "s=-\n" +
                            "c=IN IP4 172.18.18.52\n" +
                            "m=audio 49172 RTP/AVP 11\n" +
                            "a=rtpmap:11 L16/44100";
            byte[] contents = sdpData.getBytes();

            ContentTypeHeader contentTypeHeader = headerFactory.createContentTypeHeader("application", "sdp");
            invite.setContent(contents, contentTypeHeader);

            return sendRequest(invite);
        } catch (ParseException | InvalidArgumentException e) {
            return false;
        }
    }
    public Address getMySipAddress() {
        return createSipUserAddress(myUserName, myDomainName);
    }

    private Address createSipUserAddress(String name, String domain) {
        try {
            return addressFactory.createAddress(String.format("%s <sip:%s@%s;transport=%s>",
                    name, name, domain, myTransportProtocol));
        } catch (ParseException e) {
            e.printStackTrace();
            return null;
        }
    }
    @Override
    public void processRequest(RequestEvent requestEvent) {

    }

    @Override
    public void processResponse(ResponseEvent responseEvent) {
        Response response = responseEvent.getResponse();
    String method = responseEvent.getClientTransaction().getRequest().getMethod();
    int statusCode = responseEvent.getResponse().getStatusCode();

        if (statusCode == 200 && method.equalsIgnoreCase("REGISTER")) {
        changeClientStatusTo(REGISTERED);
    }

        if (statusCode == 100 && method.equalsIgnoreCase("INVITE")) {
        changeClientStatusTo(TRYING);
    }

        if (statusCode == 180 && method.equalsIgnoreCase("INVITE")) {
        changeClientStatusTo(RINGING);
    }

        if (statusCode == 200 && method.equalsIgnoreCase("INVITE")) {
        // DO SOMETHING
    }
}

    @Override
    public void processTimeout(TimeoutEvent timeoutEvent) { }

    @Override
    public void processIOException(IOExceptionEvent exceptionEvent) { }

    @Override
    public void processTransactionTerminated(TransactionTerminatedEvent transactionTerminatedEvent) { }

    @Override
    public void processDialogTerminated(DialogTerminatedEvent dialogTerminatedEvent) { }
}

被叫方:

import mypackage.voip.model.ClientStatus;
import gov.nist.javax.sip.address.AddressFactoryImpl;
import gov.nist.javax.sip.header.HeaderFactoryImpl;
import gov.nist.javax.sip.header.SIPHeaderNames;
import gov.nist.javax.sip.message.MessageFactoryImpl;

import javax.sip.*;
import javax.sip.address.Address;
import javax.sip.address.SipURI;
import javax.sip.header.*;
import javax.sip.message.Request;
import javax.sip.message.Response;
import java.text.ParseException;
import java.util.Arrays;
import java.util.List;
import java.util.Properties;
import java.util.TooManyListenersException;

import static mypackage.voip.model.ClientStatus.DISCONNECTED;
import static mypackage.voip.model.ClientStatus.INVITED;
import static mypackage.voip.model.ClientStatus.REGISTERING;
import static javax.sip.message.Response.OK;
import static javax.sip.message.Response.RINGING;

public class Callee implements SipListener {
    private int myPort;
    private String myIpAddress;
    private String myUserName;
    private ClientStatus clientStatus = DISCONNECTED;
    private SipStack sipStack;
    private SipProvider sipProvider = null;
    private MessageFactoryImpl messageFactory;
    private HeaderFactoryImpl headerFactory;
    private AddressFactoryImpl addressFactory;
    private String myTransportProtocol = "UDP";

    public Callee(String name, String ip, int port, String protocol) {
        this.myUserName = name;
        this.myTransportProtocol = protocol;
        this.myIpAddress = ip;
        this.myPort = port;
        changeClientStatusTo(DISCONNECTED);
    }

    void init() throws PeerUnavailableException, TooManyListenersException {
        SipFactory sipFactory = SipFactory.getInstance();
        Properties properties = new Properties();
        properties.setProperty("javax.sip.STACK_NAME", myIpAddress + ":" + myPort);
        addressFactory = new AddressFactoryImpl();
        messageFactory = new MessageFactoryImpl();
        headerFactory = new HeaderFactoryImpl();
        sipProvider = getSipProvider();
    }

    @Override
    public void processRequest(RequestEvent requestEvent) {
        Request request = requestEvent.getRequest();
        Header from = request.getHeader(SIPHeaderNames.FROM);
        Header to = request.getHeader(SIPHeaderNames.TO);
        Header contact = request.getHeader(SIPHeaderNames.CONTACT);
        Header via = request.getHeader(SIPHeaderNames.VIA);

        ServerTransaction serverTransactionId = requestEvent.getServerTransaction();
        if (request.getMethod().equals(Request.INVITE)) {
            processInvite(requestEvent);
        } else if (request.getMethod().equals(Request.ACK)) {
            // DO SOMETHING
        } else if (request.getMethod().equals(Request.CANCEL)) {
            // DO SOMETHING
        } else if (request.getMethod().equals(Request.BYE)) {
            // DO SOMETHING
        }
        else{
                // DO SOMETHING
            }
    }

    @Override
    public void processResponse(ResponseEvent responseEvent) {

    }

    public void doRegistration(String registrarIp) throws ParseException, InvalidArgumentException {
        if (startRegistration(registrarIp)) {
            changeClientStatusTo(REGISTERING);
        }
    }

    private void changeClientStatusTo(ClientStatus newClientStatus) {
        this.clientStatus = newClientStatus;
    }

    private boolean startRegistration(String registrarIpAddress) throws ParseException, InvalidArgumentException {

        CallIdHeader callIdHeader = headerFactory.createCallIdHeader("callID");
        CSeqHeader cSeqHeader = headerFactory.createCSeqHeader(System.currentTimeMillis() / 1000L, Request.REGISTER);

        ContactHeader contactHeader = headerFactory.createContactHeader(getMyContactAddress());
        ExpiresHeader expiresHeader = headerFactory.createExpiresHeader(217);

        Address fromAddress = getMyContactAddress();
        Address toAddress = fromAddress;

        FromHeader fromHeader = headerFactory.createFromHeader(fromAddress, "tag");
        ToHeader toHeader = headerFactory.createToHeader(toAddress, "tag");

        List viaHeaders = Arrays.asList();

        MaxForwardsHeader maxForwards = headerFactory.createMaxForwardsHeader(70);


        SipURI requestURI = addressFactory.createSipURI("sip:" + registrarIpAddress + ":5060");

        Request register = messageFactory.createRequest(requestURI,
                Request.REGISTER,
                callIdHeader,
                cSeqHeader,
                fromHeader,
                toHeader,
                viaHeaders,
                maxForwards);
        register.addHeader(contactHeader);
        register.addHeader(expiresHeader);
        return sendRequest(register);
    }

    private Address getMyContactAddress() {
        return createAddress(myUserName, myIpAddress, myPort);
    }

    private boolean sendRequest(Request request) {
        sipProvider = getSipProvider();
        try {
            ClientTransaction clientTransaction = sipProvider.getNewClientTransaction(request);
            clientTransaction.sendRequest();
            return true;
        } catch (SipException e) {
        e.printStackTrace();
        }
        return false;
    }

    private Address createAddress(String username, String hostname, int port) {
        try {
            return addressFactory.createAddress(String.format("%s <sip:%s@%s:%s;transport=%s>",
                    username,
                    username,
                    hostname,
                    port,
                    myTransportProtocol));
        } catch (ParseException e) {
            return null;
        }
    }

    private void processInvite(RequestEvent requestEvent) {
        try {
            changeClientStatusTo(INVITED);
            SipProvider sipProvider = (SipProvider) requestEvent.getSource();
            Request request = requestEvent.getRequest();

            ServerTransaction st = requestEvent.getServerTransaction();
            if (st == null) {
                st = sipProvider.getNewServerTransaction(request);
            }

            Response ringingResponse = messageFactory.createResponse(RINGING, request);
            ToHeader toHeader = (ToHeader) ringingResponse.getHeader(ToHeader.NAME);
            toHeader.setTag("foobar");
            ringingResponse.removeHeader(ToHeader.NAME);
            ringingResponse.addHeader(toHeader);
            st.sendResponse(ringingResponse);

        } catch (ParseException | InvalidArgumentException | SipException e) {
            e.printStackTrace();
        }
    }

    public ClientStatus getClientStatus() {
        return clientStatus;
    }

    private SipProvider getSipProvider() {
        try {
            ListeningPoint listeningPoint = sipStack.createListeningPoint(myIpAddress, myPort, myTransportProtocol);

            if (sipProvider != null)
                return sipProvider;

            sipProvider = sipStack.createSipProvider(listeningPoint);
            sipProvider.addSipListener(this);
            return sipProvider;
        } catch (Exception ex) {
            ex.printStackTrace();
            return null;
        }
    }

    @Override
    public void processTimeout(TimeoutEvent timeoutEvent) {
    }

    @Override
    public void processIOException(IOExceptionEvent exceptionEvent) {
    }

    @Override
    public void processTransactionTerminated(TransactionTerminatedEvent transactionTerminatedEvent) {
    }

    @Override
    public void processDialogTerminated(DialogTerminatedEvent dialogTerminatedEvent) {
    }
}

修改

我为我的场景写了一个小测试:

import org.junit.Before;
import org.junit.Test;

import javax.sdp.SdpException;
import javax.sip.InvalidArgumentException;
import javax.sip.PeerUnavailableException;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.text.ParseException;
import java.util.TooManyListenersException;

import static mypackage.voip.model.ClientStatus.*;
import static org.awaitility.Awaitility.await;
import static org.hamcrest.CoreMatchers.is;

public class CallerCalleeTest {

    private String myIpAddress;
    private String registrarIpAddress = "172.18.18.109";
    private TestRegistrar testRegistrar;
    @Test
    public void testTwoClients() throws PeerUnavailableException, UnknownHostException, TooManyListenersException,
            SdpException, ParseException, InvalidArgumentException {
        Caller caller = createAndInitializeCaller("caller", myIpAddress, 5066);
        caller.doRegistration(registrarIpAddress);
        await().until(() -> caller.getClientStatus(), is(REGISTERED));

        Callee callee = createAndInitializeCallee("callee", myIpAddress, 5067);
        callee.doRegistration(registrarIpAddress);
        await().until(() -> callee.getClientStatus(), is(REGISTERING));

        // Start the call
        caller.call("callee", myIpAddress + ":" + 5067);
        await().until(() -> caller.getClientStatus(), is(WAIT_AFTER_INVITE));
        await().until(() -> callee.getClientStatus(), is(INVITED));
    }

    @Before
    public void setup() throws UnknownHostException, PeerUnavailableException, TooManyListenersException {
        myIpAddress = InetAddress.getLocalHost().getHostAddress();
    }

    private static Caller createAndInitializeCaller(String username, String ipAddress, int port) throws
            PeerUnavailableException, TooManyListenersException {
        Caller classUnderTestUdp = new Caller(username, ipAddress, port, "UDP");
        classUnderTestUdp.init();
        return classUnderTestUdp;
    }

    private static Callee createAndInitializeCallee(String username, String ipAddress, int port) throws
            PeerUnavailableException, TooManyListenersException {
        Callee callee = new Callee(username, ipAddress, port, "UDP");
        callee.init();
        return callee;
    }    
}

注册官是siproxd

这是Wireshark-Dump

0 个答案:

没有答案