1

I am building a java application using SIP over websockets and working as b2bua, i.e. this application registers a number of sip users on another SIP server.

I was wondering if there is a way to somehow reuse an existing listening point? It seems that for each of the SIP clients I should create SipStack, SipListeningPoint, SipProvider and then call SipProvider's sendRequest to actually send SIP message to the destination server. The creation of a SipListeningPoint however allocates a new socket to accept incoming connections (which I don't really need), so I need one open socket for each SIP client I am registering on the remote server.

I tried to reuse SipListeningPoint, but there is a limitation that only one listening point is allowed per SipStack. I also tried to reuse SipProvider, but it leads to an exception in SSLStateMachine.

javax.net.ssl.SSLException: Received fatal alert: handshake_failure
    at sun.security.ssl.Alerts.getSSLException(Alerts.java:208)
    at sun.security.ssl.SSLEngineImpl.fatal(SSLEngineImpl.java:1666)
    at sun.security.ssl.SSLEngineImpl.fatal(SSLEngineImpl.java:1634)
    at sun.security.ssl.SSLEngineImpl.recvAlert(SSLEngineImpl.java:1800)
    at sun.security.ssl.SSLEngineImpl.readRecord(SSLEngineImpl.java:1083)
    at sun.security.ssl.SSLEngineImpl.readNetRecord(SSLEngineImpl.java:907)
    at sun.security.ssl.SSLEngineImpl.unwrap(SSLEngineImpl.java:781)
    at javax.net.ssl.SSLEngine.unwrap(SSLEngine.java:624)
    at gov.nist.javax.sip.stack.SSLStateMachine.unwrap(SSLStateMachine.java:303)
    at gov.nist.javax.sip.stack.SSLStateMachine.unwrap(SSLStateMachine.java:244)
    at gov.nist.javax.sip.stack.NioTlsWebSocketMessageChannel.addBytes(NioTlsWebSocketMessageChannel.java:282)
    at gov.nist.javax.sip.stack.NioTcpMessageChannel.readChannel(NioTcpMessageChannel.java:121)
    at gov.nist.javax.sip.stack.NioTcpMessageProcessor$ProcessorTask.read(NioTcpMessageProcessor.java:154)
    at gov.nist.javax.sip.stack.NioTcpMessageProcessor$ProcessorTask.run(NioTcpMessageProcessor.java:344)
    at java.lang.Thread.run(Thread.java:745)

(Yes I know that this stack trace usually means that there is some issue with an SSL certificate. But SSL connection establishes successfully when I create separate listening points for each sip user or when I register just one sip user)

Here are SipStack properties I set:

properties.setProperty("javax.sip.STACK_NAME", s"im.dlg.sip:$localAddress:$transport")
properties.setProperty("javax.sip.AUTOMATIC_DIALOG_SUPPORT", "on") // must be on to leverage dialog usage!
properties.setProperty("gov.nist.javax.sip.DELIVER_RETRANSMITTED_ACK_TO_LISTENER", "true")
properties.setProperty("gov.nist.javax.sip.REENTRANT_LISTENER", "false")
properties.setProperty("gov.nist.javax.sip.MESSAGE_PROCESSOR_FACTORY", "gov.nist.javax.sip.stack.NioMessageProcessorFactory")
properties.setProperty("gov.nist.javax.sip.THREAD_POOL_SIZE", "10")

I am using javax.sip:jain-sip-ri:1.2.265.

user1256821
  • 1,158
  • 3
  • 15
  • 35
  • The rule is that a socket is reused per (source,dest) pair so that it tunnels calls efficiently. If you are acting as a gateway you should be able to tunnel all your different client's traffic through a single socket. There should be no reason to open a new socket for each client, as long as the call id and from/to strings are different the SIP doesn't care about the transport layer. If you can't reuse the socket then you've already given up on most of the efficiency of the protocol so it wouldn't matter if you have to create a new provider per client. I don't see the user case. Any details? – Vladimir Ralev Nov 13 '17 at 16:48
  • Vladimir, thank you for your reply. Please check the original question; I've added some details. What should be the correct approach in my case (registering many clients on a single server)? I should create just one instance of each of `SipStack`, `SipListeningPoint` and `SipProvider`? That's what I do now and I'm getting the aforementioned exception. – user1256821 Nov 13 '17 at 21:55
  • It seems to be a threading issue because it's gone after I added a random sleep just before calling to `sipProvider.getNewClientTransaction`. But as far as I can see JAIN SIP is thread safe, at least for sending requests? – user1256821 Nov 13 '17 at 22:18
  • Unless there is some problem in your counterparty you should just use a single stack and single socket to send all your calls through it. I see may be you are hitting some bug, somehow you end up sending data before handshaking is complete, I don't understand how this happens, can you give more details, is this TLS client or server mode and is it outbound or inbound request. Any sample code to reproduce the issue? If this is WSS client outbound - maybe it's bad. I guess as a workaround you could pause a sec after your very first activity on the socket to make sure the handshake is complete. – Vladimir Ralev Nov 14 '17 at 17:30
  • @VladimirRalev I've created a sample project on GitHub: https://github.com/bmaslakov/sip-test. To reproduce the issue it's enough to create two threads registering two WSS SIP users concurrently. – user1256821 Nov 15 '17 at 10:02
  • Thanks. I will look into it. – Vladimir Ralev Nov 15 '17 at 17:04
  • I am getting a "Certificate chaining error" on your server. Do I need a special cert? I am gonna try to reproduce against nginx since i can't normally. – Vladimir Ralev Nov 16 '17 at 16:39
  • Yes, unfortunately, this host uses self-signed cert and you have to add it using java's keytool – user1256821 Nov 16 '17 at 21:51
  • OK I was able to reproduce the issue. Working on the fix https://github.com/usnistgov/jsip/issues/30 – Vladimir Ralev Nov 17 '17 at 13:47
  • You can try this branch while I am testing, should work fine https://github.com/vladimirralev/jsip/tree/issue30 – Vladimir Ralev Nov 18 '17 at 09:49

0 Answers0