/** * * * <pre> * Alice Proxy Bob Bob(2) HSS * 1 | INVITE | | | | * |----------->| | | | * 2 | | INVITE | | | * | |--------->| | | * 3 | | 404 | | | * | |<---------| | | * 4 | | ACK | | | * | |--------->| | | * 5 | | UDR | | | * | |--------------------------------->| * 6 | | | | UDA | * | |<---------------------------------| * 7 | | INVITE | | | * | |--------------------->| | * 8 | | | 200 | | * | |<---------------------| | * 9 | 200 | | | | * |<-----------| | | | * 10 | ACK | | | | * |----------->| | | | * 11 | | ACK | | | * | |--------------------->| | * 12 | BYE | | | | * |----------->| | | | * 13 | | BYE | | | * | |--------------------->| | * 14 | | | 200 | | * | |<---------------------| | * 15 | 200 | | | | * |<-----------| | | | * </pre> */ @Test public void testProxyDiameter() throws Throwable { Endpoint bob = createEndpoint("bob"); UaRunnable callB = new UasScript.NotFound(bob.getUserAgent()); Endpoint bob2 = createEndpoint("bob"); UaRunnable callC = new UasScript.OkBye(bob2.getUserAgent()); callB.start(); callC.start(); SipServletRequest request = _ua.createRequest(SipMethods.INVITE, bob.getUri()); request.setRequestURI(bob.getContact().getURI()); request.addHeader("proxy", bob2.getContact().toString()); Call callA = _ua.createCall(request); try { assertThat(callA.waitForResponse(), isSuccess()); callA.createAck().send(); Thread.sleep(200); callA.createBye().send(); assertThat(callA.waitForResponse(), isSuccess()); callB.assertDone(); callC.assertDone(); } finally { checkForFailure(); } }
@Override public synchronized void forwardTo(final Endpoint endpoint, final Map<String, String> headers) throws SignalException, IllegalStateException { URI target = null; try { target = _ctx.getSipFactory().createURI(endpoint.getURI().toString()); } catch (final ServletParseException e) { throw new IllegalArgumentException(e); } this.checkState(); _forwarded = true; final SipServletRequest req = _ctx.getSipFactory() .createRequest( _req.getApplicationSession(), _req.getMethod(), _req.getFrom(), _req.getTo()); req.setRequestURI(target); SIPHelper.addHeaders(req, headers); SIPHelper.copyContent(_req, req); SIPHelper.linkSIPMessage(_req, req); try { req.send(); } catch (final IOException e) { throw new SignalException(e); } }
/** * * * <pre> * Alice Proxy Bob * 1 | INVITE | | * |----------->| | * 2 | | INVITE | * | |----------->| * 3 | | 180 | * | |<-----------| * 4 | 180 | | * |<-----------| | * 5 | | CANCEL | * | |----------->| * 6 | 408 | | * |<-----------| | * 7 | | 200/CANCEL | * | |<-----------| * 8 | | 487/INVITE | * | |<-----------| * 9 | | ACK | * | |----------->| * 10 | ACK | | * |----------->| | * </pre> */ @Test public void testVirtualBranch() throws Exception { Endpoint bob = createEndpoint("bob"); UaRunnable callB = new UasScript.RingingCanceled(bob.getUserAgent()); callB.start(); SipServletRequest request = _ua.createRequest(SipMethods.INVITE, bob.getUri()); request.setRequestURI(bob.getContact().getURI()); Call callA = _ua.createCall(request); assertThat(callA.waitForResponse(), hasStatus(SipServletResponse.SC_REQUEST_TIMEOUT)); checkForFailure(); }
/** * Ensure that the servlet is not invoked if session is invalidated. * * <p>See http://jira.cipango.org/browse/CIPANGO-121 * * <pre> * Alice Proxy Bob * 1 | INVITE | | * |----------->| | * 2 | | INVITE | * | |--------->| * 3 | | 200 | * | |<---------| * 4 | 200 | | * |<-----------| | * 5 | ACK | | * |----------->| | * 6 | | ACK | * | |--------->| * 7 | BYE | | * |----------->| | * 8 | | BYE | * | |--------->| * 9 | | 200 | * | |<---------| * 10 | 200 | | * |<-----------| | * </pre> */ @Test public void testInvalidateBefore200() throws Exception { Endpoint bob = createEndpoint("bob"); UaRunnable callB = new UasScript.OkBye(bob.getUserAgent()); callB.start(); SipServletRequest request = _ua.createRequest(SipMethods.INVITE, bob.getUri()); request.setRequestURI(bob.getContact().getURI()); Call callA = _ua.createCall(request); assertThat(callA.waitForResponse(), isSuccess()); callA.createAck().send(); callA.createBye().send(); SipServletResponse response = callA.waitForResponse(); assertThat(response, isSuccess()); assertThat(response.getHeader("error"), is(nullValue())); }
/** * Ensures that - DNS resolution is done using NAPTR and SRV in proxy mode; - retry is done if a * 503 is received. * * <p>To run this test, the DNS server for domain cipango.voip should be configured with * * <pre> * bob IN NAPTR 90 40 "s" "SIP+D2U" "" _sip._udp.bob * _sip._udp.bob SRV 0 0 5064 local * _sip._udp.bob SRV 5 0 5063 local * </pre> * * Note:This test is marked as ignored as it requires a specific DNS configuration. */ @Ignore public void dnsCase() throws Exception { final Endpoint bob = createEndpoint("bob"); bob.getUserAgent() .setDefaultHandler( new MessageHandler() { public void handleRequest(SipServletRequest request) throws IOException, ServletException { SipServletResponse response = bob.getUserAgent().createResponse(request, SipServletResponse.SC_ACCEPTED); response.addHeader("X-Dns", "ok"); response.send(); } public void handleResponse(SipServletResponse response) throws IOException, ServletException {} }); final Endpoint bob2 = createEndpoint("bob"); bob2.getUserAgent() .setDefaultHandler( new MessageHandler() { public void handleRequest(SipServletRequest request) throws IOException, ServletException { SipServletResponse response = bob.getUserAgent() .createResponse(request, SipServletResponse.SC_SERVICE_UNAVAILABLE); response.send(); } public void handleResponse(SipServletResponse response) throws IOException, ServletException {} }); SipServletRequest request = _ua.createRequest(SipMethods.MESSAGE, bob.getUri()); request.setRequestURI(_sipClient.getFactory().createURI("sip:bob.cipango.voip")); Call call = _ua.createCall(request); assertThat(call.waitForResponse(), hasStatus(SipServletResponse.SC_ACCEPTED)); checkForFailure(); }
/** * * * <pre> * Alice Proxy Proxy Bob * 1 | INVITE | | | * |------------>| | | * 2 | |INVITE tel:1234 | | * | |---------------->| | * 3 | | | INVITE | * | | |--------->| * 4 | | | 603 | * | | |<---------| * 5 | | 603 | | * | |<----------------| | * 6 | 603 | | | * |<------------| | | * 7 | ACK | | | * |------------>| | | * 8 | |ACK | | * | |---------------->| | * 9 | | | ACK | * | | |--------->| * </pre> */ @Test public void testTelUri() throws Exception { final Endpoint bob = createEndpoint("bob"); bob.getUserAgent() .setDefaultHandler( new MessageHandler() { public void handleRequest(SipServletRequest request) throws IOException, ServletException { assertThat(request.getHeader("req-uri"), containsString("tel:1234")); bob.getUserAgent().createResponse(request, SipServletResponse.SC_DECLINE).send(); } public void handleResponse(SipServletResponse response) throws IOException, ServletException {} }); SipServletRequest request = _ua.createRequest(SipMethods.INVITE, bob.getUri()); request.setRequestURI(bob.getContact().getURI()); Call call = _ua.createCall(request); assertThat(call.waitForResponse(), hasStatus(SipServletResponse.SC_DECLINE)); }
/** * @param request * @param client * @param toClient * @throws IOException */ public static boolean redirectToB2BUA( final SipServletRequest request, final Client client, Client toClient, DaoManager storage, SipFactory sipFactory) throws IOException { request.getSession().setAttribute("lastRequest", request); if (logger.isInfoEnabled()) { logger.info("B2BUA (p2p proxy): Got request:\n" + request.getMethod()); logger.info( String.format( "B2BUA: Proxying a session between %s and %s", client.getUri(), toClient.getUri())); } if (daoManager == null) { daoManager = storage; } String user = ((SipURI) request.getTo().getURI()).getUser(); final RegistrationsDao registrations = daoManager.getRegistrationsDao(); final Registration registration = registrations.getRegistration(user); if (registration != null) { final String location = registration.getLocation(); SipURI to; SipURI from; try { to = (SipURI) sipFactory.createURI(location); from = (SipURI) sipFactory.createURI( (registrations.getRegistration(client.getLogin())).getLocation()); final SipSession incomingSession = request.getSession(); // create and send the outgoing invite and do the session linking incomingSession.setAttribute(B2BUA_LAST_REQUEST, request); SipServletRequest outRequest = sipFactory.createRequest( request.getApplicationSession(), request.getMethod(), request.getFrom().getURI(), request.getTo().getURI()); outRequest.setRequestURI(to); if (request.getContent() != null) { final byte[] sdp = request.getRawContent(); String offer = null; if (request.getContentType().equalsIgnoreCase("application/sdp")) { // Issue 308: https://telestax.atlassian.net/browse/RESTCOMM-308 String externalIp = request.getInitialRemoteAddr(); // Issue 306: https://telestax.atlassian.net/browse/RESTCOMM-306 final String initialIpBeforeLB = request.getHeader("X-Sip-Balancer-InitialRemoteAddr"); try { if (initialIpBeforeLB != null && !initialIpBeforeLB.isEmpty()) { offer = patch(sdp, initialIpBeforeLB); } else { offer = patch(sdp, externalIp); } } catch (SdpException e) { logger.error("Unexpected exception while patching sdp ", e); } } if (offer != null) { outRequest.setContent(offer, request.getContentType()); } else { outRequest.setContent(sdp, request.getContentType()); } } final SipSession outgoingSession = outRequest.getSession(); if (request.isInitial()) { incomingSession.setAttribute(B2BUA_LINKED_SESSION, outgoingSession); outgoingSession.setAttribute(B2BUA_LINKED_SESSION, incomingSession); } outgoingSession.setAttribute(B2BUA_LAST_REQUEST, outRequest); request.createResponse(100).send(); // Issue #307: https://telestax.atlassian.net/browse/RESTCOMM-307 request.getSession().setAttribute("toInetUri", to); outRequest.send(); outRequest.getSession().setAttribute("fromInetUri", from); final CallDetailRecord.Builder builder = CallDetailRecord.builder(); builder.setSid(Sid.generate(Sid.Type.CALL)); builder.setDateCreated(DateTime.now()); builder.setAccountSid(client.getAccountSid()); builder.setTo(toClient.getFriendlyName()); builder.setCallerName(client.getFriendlyName()); builder.setFrom(client.getFriendlyName()); // builder.setForwardedFrom(callInfo.forwardedFrom()); // builder.setPhoneNumberSid(phoneId); builder.setStatus(CallStateChanged.State.QUEUED.name()); builder.setDirection("Client-To-Client"); builder.setApiVersion(client.getApiVersion()); builder.setPrice(new BigDecimal("0.00")); // TODO implement currency property to be read from Configuration builder.setPriceUnit(Currency.getInstance("USD")); final StringBuilder buffer = new StringBuilder(); buffer.append("/").append(client.getApiVersion()).append("/Accounts/"); buffer.append(client.getAccountSid().toString()).append("/Calls/"); buffer.append(client.getSid().toString()); final URI uri = URI.create(buffer.toString()); builder.setUri(uri); CallDetailRecordsDao records = daoManager.getCallDetailRecordsDao(); CallDetailRecord callRecord = builder.build(); records.addCallDetailRecord(callRecord); incomingSession.setAttribute(CDR_SID, callRecord.getSid()); outgoingSession.setAttribute(CDR_SID, callRecord.getSid()); return true; // successfully proxied the SIP request between two registered clients } catch (ServletParseException badUriEx) { if (logger.isInfoEnabled()) { logger.info( String.format("B2BUA: Error parsing Client Contact URI: %s", location), badUriEx); } } } return false; }