Skip to content

Commit

Permalink
Validage for WebRTC call by checking SDP.
Browse files Browse the repository at this point in the history
 This close #1379
  • Loading branch information
gvagenas committed Sep 19, 2016
1 parent d89836b commit 41b8255
Show file tree
Hide file tree
Showing 3 changed files with 185 additions and 2 deletions.
Expand Up @@ -123,4 +123,16 @@ private static void fix(final Connection connection, final String externalIp) th
}
}

public static boolean isWebRTCSDP(final String contentType, final byte[] data) throws SdpParseException {
boolean isWebRTC = false;
if (contentType.equalsIgnoreCase("application/sdp")) {
String sdp = getSdp(contentType, data);
if (sdp != null && sdp.contains("RTP/SAVP") || sdp.contains("rtp/savp")
|| sdp.contains("RTP/SAVPF") || sdp.contains("rtp/savpf")) {
isWebRTC = true;
}
}
return isWebRTC;
}

}
Expand Up @@ -41,6 +41,7 @@
import java.util.concurrent.atomic.AtomicInteger;
import java.util.regex.Pattern;

import javax.sdp.SdpParseException;
import javax.servlet.ServletContext;
import javax.servlet.sip.Address;
import javax.servlet.sip.AuthInfo;
Expand Down Expand Up @@ -79,6 +80,7 @@
import org.mobicents.servlet.restcomm.patterns.StopObserving;
import org.mobicents.servlet.restcomm.telephony.util.B2BUAHelper;
import org.mobicents.servlet.restcomm.telephony.util.CallControlHelper;
import org.mobicents.servlet.restcomm.util.SdpUtils;
import org.mobicents.servlet.restcomm.util.UriUtils;

import scala.concurrent.Await;
Expand Down Expand Up @@ -470,9 +472,19 @@ private boolean isWebRTC(final SipServletRequest request) {
if (userAgent != null && !userAgent.isEmpty() && userAgent.equalsIgnoreCase("wss-sipunit")) {
return true;
}
if (!request.getInitialTransport().equalsIgnoreCase(transport))
if (!request.getInitialTransport().equalsIgnoreCase(transport)) {
transport = request.getInitialTransport();
return "ws".equalsIgnoreCase(transport) || "wss".equalsIgnoreCase(transport);
if ("ws".equalsIgnoreCase(transport) || "wss".equalsIgnoreCase(transport))
return true;
}
try {
if (SdpUtils.isWebRTCSDP(request.getContentType(), request.getRawContent())) {
return true;
}
} catch (SdpParseException e) {}
catch (IOException e) {}

return false;
}

private void proxyThroughMediaServer(final SipServletRequest request, final Client client, final String destNumber) {
Expand Down
Expand Up @@ -67,6 +67,105 @@ public class ClientsDialTest {
86, 80, 32, 48, 13, 10, 97, 61, 114, 116, 112, 109, 97, 112, 58, 48, 32, 80, 67, 77, 85, 47, 56, 48, 48, 48, 13, 10 };
private static final String body = new String(bytes);

private static final String webRtcBody = "v=0\n" +
"o=- 655836341935372758 2 IN IP4 24.217.142.20\n" +
"s=Restcomm B2BUA\n" +
"t=0 0\n" +
"a=group:BUNDLE audio video\n" +
"a=msid-semantic:WMS ARDAMS\n" +
"m=audio 9 UDP/TLS/RTP/SAVPF 111 103 9 102 0 8 106 105 13 126\n" +
"c=IN IP4 24.217.142.20\n" +
"a=rtcp:9 IN IP4 0.0.0.0\n" +
"a=candidate:704553097 1 udp 2122260223 192.168.1.3 60475 typ host generation 0 ufrag PFs2 network-id 3 network-cost 10\n" +
"a=candidate:2158047068 1 udp 1686052607 24.217.142.20 60475 typ srflx raddr 192.168.1.3 rport 60475 generation 0 ufrag PFs2 network-id 3 network-cost 10\n" +
"a=candidate:152961445 1 udp 41885695 50.97.253.79 55954 typ relay raddr 24.217.142.20 rport 60475 generation 0 ufrag PFs2 network-id 3 network-cost 10\n" +
"a=candidate:152961445 1 udp 41886207 50.97.253.79 49214 typ relay raddr 24.217.142.20 rport 60475 generation 0 ufrag PFs2 network-id 3 network-cost 10\n" +
"a=candidate:1201536341 1 udp 25108735 50.97.253.79 63824 typ relay raddr 24.217.142.20 rport 54517 generation 0 ufrag PFs2 network-id 3 network-cost 10\n" +
"a=candidate:1201536341 1 udp 25108223 50.97.253.79 50246 typ relay raddr 24.217.142.20 rport 33927 generation 0 ufrag PFs2 network-id 3 network-cost 10\n" +
"a=ice-ufrag:PFs2\n" +
"a=ice-pwd:MZHsJBkJ+vdWaNvb4Z7iCejt\n" +
"a=fingerprint:sha-256 56:B1:98:06:06:EA:B1:BB:31:51:28:35:C7:8C:45:11:CD:3A:0D:28:C1:10:5B:D5:99:EA:21:46:8E:ED:08:89\n" +
"a=setup:actpass\n" +
"a=mid:audio\n" +
"a=extmap:1 urn:ietf:params:rtp-hdrext:ssrc-audio-level\n" +
"a=extmap:3 http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time\n" +
"a=sendrecv\n" +
"a=rtcp-mux\n" +
"a=rtpmap:111 opus/48000/2\n" +
"a=rtcp-fb:111 transport-cc\n" +
"a=fmtp:111 minptime=10;useinbandfec=1\n" +
"a=rtpmap:103 ISAC/16000\n" +
"a=rtpmap:9 G722/8000\n" +
"a=rtpmap:102 ILBC/8000\n" +
"a=rtpmap:0 PCMU/8000\n" +
"a=rtpmap:8 PCMA/8000\n" +
"a=rtpmap:106 CN/32000\n" +
"a=rtpmap:105 CN/16000\n" +
"a=rtpmap:13 CN/8000\n" +
"a=rtpmap:126 telephone-event/8000\n" +
"a=ssrc:743432057 cname:USPxCkO2V7yoEmg/\n" +
"a=ssrc:743432057 msid:ARDAMS ARDAMSa0\n" +
"a=ssrc:743432057 mslabel:ARDAMS\n" +
"a=ssrc:743432057 label:ARDAMSa0\n" +
"m=video 9 UDP/TLS/RTP/SAVPF 100 101 116 117 121 96 97 98 99\n" +
"c=IN IP4 24.217.142.20\n" +
"a=rtcp:9 IN IP4 0.0.0.0\n" +
"a=candidate:704553097 1 udp 2122260223 192.168.1.3 40839 typ host generation 0 ufrag PFs2 network-id 3 network-cost 10\n" +
"a=candidate:2158047068 1 udp 1686052607 24.217.142.20 40839 typ srflx raddr 192.168.1.3 rport 40839 generation 0 ufrag PFs2 network-id 3 network-cost 10\n" +
"a=candidate:152961445 1 udp 41886207 50.97.253.79 53691 typ relay raddr 24.217.142.20 rport 40839 generation 0 ufrag PFs2 network-id 3 network-cost 10\n" +
"a=candidate:152961445 1 udp 41885695 50.97.253.79 63503 typ relay raddr 24.217.142.20 rport 40839 generation 0 ufrag PFs2 network-id 3 network-cost 10\n" +
"a=candidate:1201536341 1 udp 25108735 50.97.253.79 56359 typ relay raddr 24.217.142.20 rport 33643 generation 0 ufrag PFs2 network-id 3 network-cost 10\n" +
"a=candidate:1201536341 1 udp 25108223 50.97.253.79 54107 typ relay raddr 24.217.142.20 rport 44827 generation 0 ufrag PFs2 network-id 3 network-cost 10\n" +
"a=ice-ufrag:PFs2\n" +
"a=ice-pwd:MZHsJBkJ+vdWaNvb4Z7iCejt\n" +
"a=fingerprint:sha-256 56:B1:98:06:06:EA:B1:BB:31:51:28:35:C7:8C:45:11:CD:3A:0D:28:C1:10:5B:D5:99:EA:21:46:8E:ED:08:89\n" +
"a=setup:actpass\n" +
"a=mid:video\n" +
"a=extmap:2 urn:ietf:params:rtp-hdrext:toffset\n" +
"a=extmap:3 http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time\n" +
"a=extmap:4 urn:3gpp:video-orientation\n" +
"a=extmap:6 http://www.webrtc.org/experiments/rtp-hdrext/playout-delay\n" +
"a=sendrecv\n" +
"a=rtcp-mux\n" +
"a=rtcp-rsize\n" +
"a=rtpmap:100 VP8/90000\n" +
"a=rtcp-fb:100 ccm fir\n" +
"a=rtcp-fb:100 nack\n" +
"a=rtcp-fb:100 nack pli\n" +
"a=rtcp-fb:100 goog-remb\n" +
"a=rtcp-fb:100 transport-cc\n" +
"a=rtpmap:101 VP9/90000\n" +
"a=rtcp-fb:101 ccm fir\n" +
"a=rtcp-fb:101 nack\n" +
"a=rtcp-fb:101 nack pli\n" +
"a=rtcp-fb:101 goog-remb\n" +
"a=rtcp-fb:101 transport-cc\n" +
"a=rtpmap:116 red/90000\n" +
"a=rtpmap:117 ulpfec/90000\n" +
"a=rtpmap:121 H264/90000\n" +
"a=rtcp-fb:121 ccm fir\n" +
"a=rtcp-fb:121 nack\n" +
"a=rtcp-fb:121 nack pli\n" +
"a=rtcp-fb:121 goog-remb\n" +
"a=rtcp-fb:121 transport-cc\n" +
"a=rtpmap:96 rtx/90000\n" +
"a=fmtp:96 apt=100\n" +
"a=rtpmap:97 rtx/90000\n" +
"a=fmtp:97 apt=101\n" +
"a=rtpmap:98 rtx/90000\n" +
"a=fmtp:98 apt=116\n" +
"a=rtpmap:99 rtx/90000\n" +
"a=fmtp:99 apt=121\n" +
"a=ssrc-group:FID 2457543170 3154322644\n" +
"a=ssrc:2457543170 cname:USPxCkO2V7yoEmg/\n" +
"a=ssrc:2457543170 msid:ARDAMS ARDAMSv0\n" +
"a=ssrc:2457543170 mslabel:ARDAMS\n" +
"a=ssrc:2457543170 label:ARDAMSv0\n" +
"a=ssrc:3154322644 cname:USPxCkO2V7yoEmg/\n" +
"a=ssrc:3154322644 msid:ARDAMS ARDAMSv0\n" +
"a=ssrc:3154322644 mslabel:ARDAMS\n" +
"a=ssrc:3154322644 label:ARDAMSv0";

@ArquillianResource
private Deployer deployer;
@ArquillianResource
Expand Down Expand Up @@ -558,6 +657,66 @@ public void testClientDialOutPstnSimulateWebRTCClient() throws ParseException, I
// assertTrue(georgeCall.respondToDisconnect());
}

@Test //Non regression test for issue https://github.com/RestComm/Restcomm-Connect/issues/1379 - Webrtc calls from non WS clients aren't routed to PSTN #1379
public void testClientDialOutPstnWebRTCClientwithSDP() throws ParseException, InterruptedException {

assertNotNull(mariaRestcommClientSid);
assertNotNull(dimitriRestcommClientSid);

SipURI uri = mariaSipStack.getAddressFactory().createSipURI(null, "127.0.0.1:5080");
assertTrue(mariaPhone.register(uri, "maria", "1234", mariaContact, 14400, 3600));
Thread.sleep(3000);

Credential c = new Credential("127.0.0.1", "maria", "1234");
mariaPhone.addUpdateCredential(c);

final SipCall georgeCall = georgePhone.createSipCall();
georgeCall.listenForIncomingCall();


Thread.sleep(1000);

// Maria initiates a call to Dimitri
final SipCall mariaCall = mariaPhone.createSipCall();
mariaCall.initiateOutgoingCall(mariaContact, "sip:"+pstnNumber+"@127.0.0.1:5080", null, webRtcBody, "application", "sdp", null, null);
assertLastOperationSuccess(mariaCall);
assertTrue(mariaCall.waitForAuthorisation(3000));

assertTrue(mariaCall.waitOutgoingCallResponse(5 * 1000));
int responseMaria = mariaCall.getLastReceivedResponse().getStatusCode();
assertTrue(responseMaria == Response.TRYING || responseMaria == Response.RINGING);

Dialog mariaDialog = null;

if (responseMaria == Response.TRYING) {
assertTrue(mariaCall.waitOutgoingCallResponse(5 * 1000));
assertEquals(Response.RINGING, mariaCall.getLastReceivedResponse().getStatusCode());
mariaDialog = mariaCall.getDialog();
assertNotNull(mariaDialog);
}

assertTrue(mariaCall.waitOutgoingCallResponse(5 * 1000));
assertEquals(Response.OK, mariaCall.getLastReceivedResponse().getStatusCode());
assertTrue(mariaCall.sendInviteOkAck());
assertTrue(georgeCall.waitForIncomingCall(5 * 1000));
assertTrue(georgeCall.sendIncomingCallResponse(Response.RINGING, "RINGING-George", 3600));

SipRequest lastReceivedRequest = georgeCall.getLastReceivedRequest();
String receivedBody = new String(lastReceivedRequest.getRawContent());
assertTrue(georgeCall.sendIncomingCallResponse(Response.OK, "OK-George", 3600, receivedBody, "application", "sdp", null,
null));

// For a reason the ACK will never reach Restcomm. This is only when working with the sipUnit
// assertTrue(georgeCall.waitForAck(5 * 1000));

Thread.sleep(3000);
georgeCall.listenForDisconnect();
assertTrue(mariaCall.disconnect());

// assertTrue(georgeCall.waitForDisconnect(5 * 1000));
// assertTrue(georgeCall.respondToDisconnect());
}

@Test
public void testClientDialToInvalidNumber() throws ParseException, InterruptedException, InvalidArgumentException, SipException {
String invalidNumber = "+123456789";
Expand Down

0 comments on commit 41b8255

Please sign in to comment.