use of javax.sip.address.SipURI in project load-balancer by RestComm.
the class SIPBalancerForwarder method patchSipMessageForNAT.
/**
* Patch Response for NAT Environment where the Load Balancer runs on a private IP but UAs need to know the LB public IP to
* send back subsequent requests to it.
* @param sipMessage the response to patch
* @throws PeerUnavailableException
* @throws ParseException
*/
public void patchSipMessageForNAT(javax.sip.message.Message sipMessage, boolean isIpv6) {
// Need to patch the response so the subsequent requests are directly correctly at the public IP Address of the LB
// Useful for NAT environment such as Amazon EC2
String currentPublicIp = null;
if (!isIpv6)
currentPublicIp = balancerRunner.balancerContext.publicIP;
else
currentPublicIp = balancerRunner.balancerContext.publicIPv6;
if (currentPublicIp != null && !currentPublicIp.isEmpty()) {
int[] ports = new int[5];
// int wssPort = 0;
if (!isIpv6) {
for (int i = 0; i < 5; i++) ports[i] = balancerRunner.balancerContext.externalPorts[i];
// udpPort = balancerRunner.balancerContext.externalUdpPort;
// tcpPort = balancerRunner.balancerContext.externalTcpPort;
// tlsPort = balancerRunner.balancerContext.externalTlsPort;
// wsPort = balancerRunner.balancerContext.externalWsPort;
// wssPort = balancerRunner.balancerContext.externalWssPort;
} else {
for (int i = 0; i < 5; i++) ports[i] = balancerRunner.balancerContext.externalIpv6Ports[i];
// udpPort = balancerRunner.balancerContext.externalIpv6UdpPort;
// tcpPort = balancerRunner.balancerContext.externalIpv6TcpPort;
// tlsPort = balancerRunner.balancerContext.externalIpv6TlsPort;
// wsPort = balancerRunner.balancerContext.externalIpv6WsPort;
// wssPort = balancerRunner.balancerContext.externalIpv6WssPort;
}
String transport = null;
if (sipMessage instanceof Response)
transport = ((ViaHeader) sipMessage.getHeader(ViaHeader.NAME)).getTransport().toLowerCase();
else {
URI requestURI = ((Request) sipMessage).getRequestURI();
transport = ((ViaHeader) sipMessage.getHeader(ViaHeader.NAME)).getTransport().toLowerCase();
if (requestURI.isSipURI()) {
if (((SipUri) requestURI).getTransportParam() != null)
transport = ((SipUri) requestURI).getTransportParam();
}
}
String privateIp = balancerRunner.balancerContext.host;
@SuppressWarnings("unchecked") ListIterator<RecordRouteHeader> recordRouteHeaderList = sipMessage.getHeaders(RecordRouteHeader.NAME);
try {
HeaderFactory headerFactory = SipFactory.getInstance().createHeaderFactory();
Header contactHeader = null;
if (!recordRouteHeaderList.hasNext()) {
if (logger.isDebugEnabled()) {
logger.debug("Record Route header list is empty");
}
}
while (recordRouteHeaderList.hasNext()) {
RecordRouteHeader recordRouteHeader = (RecordRouteHeader) recordRouteHeaderList.next();
if (logger.isDebugEnabled()) {
logger.debug("About to check Record-Route header: " + recordRouteHeader.toString());
}
if (((SipURI) recordRouteHeader.getAddress().getURI()).getHost().equals(privateIp)) {
// If this RecordRoute header is from LB
for (int port : ports) if (((SipURI) recordRouteHeader.getAddress().getURI()).getPort() == port) {
// And if the port is the external Port
SipURI sipURI = (SipURI) recordRouteHeader.getAddress().getURI();
sipURI.setHost(currentPublicIp);
}
} else {
if (logger.isDebugEnabled()) {
logger.debug("Didn't patched the Record-Route because ip address is not the private one: " + ((SipURI) recordRouteHeader.getAddress().getURI()).getHost());
}
}
}
if (sipMessage.getHeader(ContactHeader.NAME) != null) {
final String displayedName = ((ContactHeader) sipMessage.getHeader("Contact")).getAddress().getDisplayName();
int currPort = balancerRunner.balancerContext.getExternalPortByTransport(transport, isIpv6);
if (displayedName != null && !displayedName.isEmpty()) {
final String contactURI = "sip:" + displayedName + "@" + currentPublicIp + ":" + currPort;
contactHeader = headerFactory.createHeader("Contact", contactURI);
((ContactHeader) contactHeader).getAddress().setDisplayName(displayedName);
} else {
final String contactURI = "sip:" + currentPublicIp + ":" + currPort;
contactHeader = headerFactory.createHeader("Contact", contactURI);
}
if (contactHeader != null) {
sipMessage.removeFirst("Contact");
sipMessage.addHeader(contactHeader);
}
}
if (logger.isDebugEnabled() && contactHeader != null) {
logger.debug("Patched the Contact header with : " + contactHeader.toString());
}
} catch (PeerUnavailableException peerUnavailableException) {
logger.error("Unexpected exception while forwarding the response \n" + sipMessage, peerUnavailableException);
} catch (ParseException parseException) {
logger.error("Unexpected exception while forwarding the response \n" + sipMessage, parseException);
} catch (NullPointerException e) {
logger.error("Unexpected exception while forwarding the response \n" + sipMessage, e);
}
}
}
use of javax.sip.address.SipURI in project load-balancer by RestComm.
the class SIPBalancerForwarder method getRouteHeadersMeantForLB.
private String getRouteHeadersMeantForLB(Request request, boolean isIpv6) {
@SuppressWarnings("unchecked") ListIterator<RouteHeader> headers = request.getHeaders(RouteHeader.NAME);
RouteHeader routeHeader = null;
if (headers.hasNext())
routeHeader = headers.next();
if (routeHeader != null) {
SipURI routeUri = (SipURI) routeHeader.getAddress().getURI();
String transport = ((ViaHeader) request.getHeader("Via")).getTransport();
if (routeUri.getTransportParam() != null)
transport = routeUri.getTransportParam();
Boolean isRouteHeaderExternal = isHeaderExternal(routeUri.getHost(), routeUri.getPort(), transport, isIpv6);
if (!isRouteHeaderExternal) {
routeHeader = null;
if (headers.hasNext())
routeHeader = headers.next();
if (routeHeader != null) {
routeUri = (SipURI) routeHeader.getAddress().getURI();
transport = ((ViaHeader) request.getHeader("Via")).getTransport();
if (routeUri.getTransportParam() != null)
transport = routeUri.getTransportParam();
isRouteHeaderExternal = isHeaderExternal(routeUri.getHost(), routeUri.getPort(), transport, isIpv6);
if (!isRouteHeaderExternal)
return transport;
}
return transport;
}
}
return null;
}
use of javax.sip.address.SipURI in project load-balancer by RestComm.
the class SIPBalancerForwarder method removeRouteHeadersMeantForLB.
/**
* Remove the different route headers that are meant for the Load balancer.
* There is two cases here :
* <ul>
* <li>* Requests coming from external and going to the cluster : dialog creating requests can have route header so that they go through the LB and subsequent requests
* will have route headers since the LB record routed</li>
* <li>* Requests coming from the cluster and going to external : dialog creating requests can have route header so that they go through the LB - those requests will define in the route header
* the originating node of the request so that that subsequent requests are routed to the originating node if still alive</li>
* </ul>
*
* @param request
*/
private RouteHeaderHints removeRouteHeadersMeantForLB(Request request, boolean isIpv6) {
if (logger.isDebugEnabled()) {
logger.debug("Checking if there is any route headers meant for the LB to remove...");
}
Node node = null;
String callVersion = null;
int numberOfRemovedRouteHeaders = 0;
if (balancerRunner.balancerContext.matchingHostnameForRoute != null) {
RouteHeader routeHeader = (RouteHeader) request.getHeader(RouteHeader.NAME);
if (routeHeader != null) {
if (logger.isDebugEnabled()) {
logger.debug("Matching host name for route is : " + balancerRunner.balancerContext.matchingHostnameForRoute);
logger.debug("Matching host name and subdomain: " + balancerRunner.balancerContext.isFilterSubdomain);
}
if (!balancerRunner.balancerContext.isFilterSubdomain) {
if (((SipURI) routeHeader.getAddress().getURI()).getHost().equals(balancerRunner.balancerContext.matchingHostnameForRoute))
request.removeFirst(RouteHeader.NAME);
} else {
if (((SipURI) routeHeader.getAddress().getURI()).getHost().endsWith("." + balancerRunner.balancerContext.matchingHostnameForRoute))
request.removeFirst(RouteHeader.NAME);
}
}
}
// Removing first routeHeader if it is for the sip balancer
RouteHeader routeHeader = (RouteHeader) request.getHeader(RouteHeader.NAME);
if (routeHeader != null) {
SipURI routeUri = (SipURI) routeHeader.getAddress().getURI();
callVersion = routeUri.getParameter(ROUTE_PARAM_NODE_VERSION);
String transport = ((ViaHeader) request.getHeader("Via")).getTransport();
if (routeUri.getTransportParam() != null)
transport = routeUri.getTransportParam();
if (!isHeaderExternal(routeUri.getHost(), routeUri.getPort(), transport, isIpv6)) {
if (logger.isDebugEnabled()) {
logger.debug("this route header is for the LB removing it " + routeUri);
}
numberOfRemovedRouteHeaders++;
request.removeFirst(RouteHeader.NAME);
routeHeader = (RouteHeader) request.getHeader(RouteHeader.NAME);
// since we used double record routing we may have 2 routes corresponding to us here
// for ACK and BYE from caller for example
node = checkRouteHeaderForSipNode(routeUri);
if (routeHeader != null) {
routeUri = (SipURI) routeHeader.getAddress().getURI();
transport = ((ViaHeader) request.getHeader("Via")).getTransport();
if (routeUri.getTransportParam() != null)
transport = routeUri.getTransportParam();
if (!isHeaderExternal(routeUri.getHost(), routeUri.getPort(), transport, isIpv6)) {
if (logger.isDebugEnabled()) {
logger.debug("this route header is for the LB removing it " + routeUri);
}
numberOfRemovedRouteHeaders++;
request.removeFirst(RouteHeader.NAME);
if (node == null) {
node = checkRouteHeaderForSipNode(routeUri);
}
// SIPP sometimes appends more headers and lets remove them here. There is no legitimate reason
// more than two SIP LB headers to be place next to each-other, so this cleanup is SAFE!
boolean moreHeaders = true;
while (moreHeaders) {
RouteHeader extraHeader = (RouteHeader) request.getHeader(RouteHeader.NAME);
if (extraHeader != null) {
SipURI u = (SipURI) extraHeader.getAddress().getURI();
transport = ((ViaHeader) request.getHeader("Via")).getTransport();
if (u.getTransportParam() != null)
transport = u.getTransportParam();
if (!isHeaderExternal(u.getHost(), u.getPort(), transport, isIpv6)) {
numberOfRemovedRouteHeaders++;
request.removeFirst(RouteHeader.NAME);
} else {
moreHeaders = false;
}
} else {
moreHeaders = false;
}
}
}
}
}
}
if (node == null) {
if (request.getRequestURI().isSipURI()) {
node = checkRouteHeaderForSipNode((SipURI) request.getRequestURI());
}
}
// logger.info(request.ge + " has this hint " + node);
ToHeader to = (ToHeader) (request.getHeader(ToHeader.NAME));
/*
* We determine if this is subsequent based on To tag instead of checking route header metadata.
*/
boolean subsequent = to.getTag() != null;
if (logger.isDebugEnabled()) {
logger.debug("Number of removed Route headers is " + numberOfRemovedRouteHeaders);
}
// https://github.com/RestComm/load-balancer/issues/128
if (numberOfRemovedRouteHeaders != 2 && subsequent && !request.getMethod().equalsIgnoreCase(Request.ACK)) {
logger.warn("A subsequent request should have two Route headers. Number of removed Route headers is " + numberOfRemovedRouteHeaders + ". This indicates a client is removing important headers.");
}
return new RouteHeaderHints(node, subsequent, callVersion);
}
use of javax.sip.address.SipURI in project load-balancer by RestComm.
the class SIPBalancerForwarder method forwardRequest.
/**
* @param requestEvent
* @param sipProvider
* @param originalRequest
* @param serverTransaction
* @param request
* @throws ParseException
* @throws InvalidArgumentException
* @throws SipException
* @throws TransactionUnavailableException
*/
private void forwardRequest(SipProvider sipProvider, Request request, boolean isIpv6) throws ParseException, InvalidArgumentException, SipException, TransactionUnavailableException {
if (logger.isDebugEnabled()) {
logger.debug("got request:\n" + request);
}
boolean isRequestFromServer = false;
if (!balancerRunner.balancerContext.isTwoEntrypoints()) {
isRequestFromServer = isViaHeaderFromServer(request);
} else {
isRequestFromServer = sipProvider.equals(balancerRunner.balancerContext.internalSipProvider) || sipProvider.equals(balancerRunner.balancerContext.internalIpv6SipProvider);
}
if (isRequestFromServer) {
ViaHeader viaHeader = (ViaHeader) request.getHeader(ViaHeader.NAME);
String host = viaHeader.getHost();
if (host.matches(".*[a-zA-Z]+.*")) {
try {
host = InetAddress.getByName(host).getHostAddress();
} catch (UnknownHostException e) {
e.printStackTrace();
}
}
int port = viaHeader.getPort();
String transport = viaHeader.getTransport().toLowerCase();
Node node = getNodeDeadOrAlive(host, port, transport);
if (node != null) {
if (logger.isDebugEnabled())
logger.debug("Updating Timestamp of node: " + node + " because of request from it");
node.updateTimerStamp();
}
}
final boolean isCancel = Request.CANCEL.equals(request.getMethod());
if (!isCancel) {
decreaseMaxForwardsHeader(sipProvider, request);
}
String outerTransport = ((ViaHeader) request.getHeader(ViaHeader.NAME)).getTransport().toLowerCase();
if (isRequestFromServer) {
Boolean hasTransport = false;
if (request.getRequestURI().isSipURI()) {
if (((SipUri) request.getRequestURI()).getTransportParam() != null) {
outerTransport = ((SipUri) request.getRequestURI()).getTransportParam();
hasTransport = true;
}
}
if (!hasTransport) {
outerTransport = getRouteHeadersMeantForLB(request, isIpv6);
if (outerTransport == null)
outerTransport = ((ViaHeader) request.getHeader(ViaHeader.NAME)).getTransport().toLowerCase();
}
}
RouteHeaderHints hints = removeRouteHeadersMeantForLB(request, isIpv6);
String version = hints.version;
if (version == null) {
version = register.getLatestVersion();
hints.version = version;
}
InvocationContext ctx = balancerRunner.getInvocationContext(version);
final String callID = ((CallIdHeader) request.getHeader(CallIdHeader.NAME)).getCallId();
String transport = null;
if (balancerRunner.balancerContext.internalTransport != null) {
if (logger.isDebugEnabled()) {
logger.debug("Set internal transport for NODE looking: " + balancerRunner.balancerContext.internalTransport);
}
transport = balancerRunner.balancerContext.internalTransport.toLowerCase();
} else if (balancerRunner.balancerContext.terminateTLSTraffic) {
switch(((ViaHeader) request.getHeader(ViaHeader.NAME)).getTransport()) {
case ListeningPoint.TLS:
transport = ListeningPoint.TCP.toLowerCase();
break;
case ListeningPointExt.WSS:
transport = ListeningPointExt.WS.toLowerCase();
break;
case ListeningPointExt.WS:
case ListeningPointExt.TCP:
case ListeningPointExt.UDP:
transport = ((ViaHeader) request.getHeader(ViaHeader.NAME)).getTransport().toLowerCase();
}
if (logger.isDebugEnabled()) {
logger.debug("Terminate TLS traffic, isRequestFromServer: " + isRequestFromServer + " transport before " + ((ViaHeader) request.getHeader(ViaHeader.NAME)).getTransport() + ", transport after " + transport);
}
} else {
transport = ((ViaHeader) request.getHeader(ViaHeader.NAME)).getTransport().toLowerCase();
}
if (hints.serverAssignedNode != null) {
String headerKey = null;
if (balancerRunner.balancerContext.sipHeaderAffinityKey.equalsIgnoreCase(ToHeader.NAME)) {
URI currURI = ((HeaderAddress) request.getHeader(balancerRunner.balancerContext.sipHeaderAffinityKey)).getAddress().getURI();
if (currURI.isSipURI())
headerKey = ((SipURI) currURI).getUser();
else
headerKey = ((TelURL) currURI).getPhoneNumber();
if (balancerRunner.balancerContext.sipHeaderAffinityKeyExclusionPattern != null && balancerRunner.balancerContext.sipHeaderAffinityKeyExclusionPattern.matcher(headerKey).matches()) {
headerKey = ((HeaderExt) request.getHeader(balancerRunner.balancerContext.sipHeaderAffinityFallbackKey)).getValue();
}
} else if (balancerRunner.balancerContext.sipHeaderAffinityKey.equalsIgnoreCase(FromHeader.NAME)) {
headerKey = ((HeaderAddress) request.getHeader(balancerRunner.balancerContext.sipHeaderAffinityKey)).getAddress().getURI().toString();
if (balancerRunner.balancerContext.sipHeaderAffinityKeyExclusionPattern != null && balancerRunner.balancerContext.sipHeaderAffinityKeyExclusionPattern.matcher(headerKey).matches()) {
headerKey = ((HeaderExt) request.getHeader(balancerRunner.balancerContext.sipHeaderAffinityFallbackKey)).getValue();
}
} else {
headerKey = ((HeaderExt) request.getHeader(balancerRunner.balancerContext.sipHeaderAffinityKey)).getValue();
}
if (logger.isDebugEnabled()) {
logger.debug("headerKey " + headerKey);
}
if (!request.getMethod().equalsIgnoreCase(Request.ACK))
ctx.balancerAlgorithm.assignToNode(headerKey, hints.serverAssignedNode);
if (logger.isDebugEnabled()) {
logger.debug("Following node information has been found in one of the route Headers " + hints.serverAssignedNode);
}
// SipURI loopbackUri = getLoopbackUri(request);
// if(loopbackUri != null) {
// loopbackUri.setHost(hints.serverAssignedNode.getIp());
// loopbackUri.setPort((Integer) hints.serverAssignedNode.getProperties().get(transport + "Port"));
// }
}
Node nextNode = null;
if (isRequestFromServer) {
if (logger.isDebugEnabled()) {
logger.debug("Request from server");
}
Header initialAddrHeader = request.getHeader("X-Sip-Balancer-InitialRemoteAddr");
Header initialPortHeader = request.getHeader("X-Sip-Balancer-InitialRemotePort");
if (initialAddrHeader != null)
request.removeHeader(initialAddrHeader.getName());
if (initialPortHeader != null)
request.removeHeader(initialPortHeader.getName());
ctx.balancerAlgorithm.processInternalRequest(request);
if (request.getMethod().equalsIgnoreCase(Request.INVITE) && ctx.balancerAlgorithm.blockInternalRequest(request)) {
Response response = balancerRunner.balancerContext.messageFactory.createResponse(Response.FORBIDDEN, request);
response.setReasonPhrase("Destination not allowed");
sipProvider.sendResponse(response);
return;
}
nextNode = hints.serverAssignedNode;
if (logger.isDebugEnabled()) {
logger.debug("nexNode " + nextNode);
}
} else {
if (logger.isDebugEnabled()) {
logger.debug("Request not from server");
}
if (hints.serverAssignedNode != null) {
SipURI loopbackUri = getLoopbackUri(request, isIpv6);
if (loopbackUri != null) {
loopbackUri.setHost(hints.serverAssignedNode.getIp());
loopbackUri.setPort(Integer.parseInt(hints.serverAssignedNode.getProperties().get(transport + "Port")));
}
}
// Request is NOT from app server, first check if we have hints in Route headers
Node assignedNode = hints.serverAssignedNode;
// If there are no hints see if there is route header pointing existing node
if (assignedNode == null) {
RouteHeader nextNodeHeader = (RouteHeader) request.getHeader(RouteHeader.NAME);
if (nextNodeHeader != null) {
URI uri = nextNodeHeader.getAddress().getURI();
if (uri instanceof SipURI) {
SipURI sipUri = (SipURI) uri;
assignedNode = getAliveNode(sipUri.getHost(), sipUri.getPort(), transport, ctx, isIpv6);
if (logger.isDebugEnabled()) {
logger.debug("Found SIP URI " + uri + " |Next node is " + assignedNode);
}
}
}
}
SipURI assignedUri = null;
// boolean nextNodeInRequestUri = false;
SipURI originalRouteHeaderUri = null;
if (assignedNode == null) {
if (hints.subsequentRequest) {
RouteHeader header = (RouteHeader) request.getHeader(RouteHeader.NAME);
if (header != null) {
assignedUri = (SipURI) header.getAddress().getURI();
originalRouteHeaderUri = (SipURI) assignedUri.clone();
request.removeFirst(RouteHeader.NAME);
} else {
if (request.getRequestURI() instanceof SipURI) {
SipURI sipUri = (SipURI) request.getRequestURI();
// nextNodeInRequestUri = true;
assignedNode = getAliveNode(sipUri.getHost(), sipUri.getPort(), transport, ctx, isIpv6);
}
}
if (logger.isDebugEnabled()) {
logger.debug("Subsequent request -> Found Route Header " + header + " |Next node is " + assignedNode);
}
} else if (request.getRequestURI() instanceof SipURI) {
SipURI sipUri = (SipURI) request.getRequestURI();
// nextNodeInRequestUri = true;
assignedNode = getAliveNode(sipUri.getHost(), sipUri.getPort(), transport, ctx, isIpv6);
if (logger.isDebugEnabled()) {
logger.debug("NOT Subsequent request -> using sipUri " + sipUri + " |Next node is " + assignedNode);
}
}
}
if (assignedNode == null) {
if (logger.isDebugEnabled()) {
logger.debug("assignedNode is null");
}
if (!securityCheck(request)) {
logger.warn("Request failed at the security check:\n" + request);
} else {
nextNode = ctx.balancerAlgorithm.processExternalRequest(request, isIpv6);
}
if (nextNode instanceof NullServerNode) {
if (logger.isDebugEnabled()) {
logger.debug("Algorithm returned a NullServerNode. We will not attempt to forward this request " + request);
}
}
if (nextNode != null) {
if (logger.isDebugEnabled()) {
String nodesString = "";
// Object[] nodes = ctx.nodes.toArray();
Object[] nodes = ctx.sipNodeMap(isIpv6).values().toArray();
for (Object n : nodes) {
nodesString += n + " , ";
}
logger.debug("Next node is not null. Assigned uri is " + assignedUri + "Available nodes: " + nodesString);
}
// Adding Route Header pointing to the node the sip balancer wants to forward to
SipURI routeSipUri;
try {
if (assignedUri == null) {
// If a next node is NOT already assigned in the dialog from previous requests
routeSipUri = balancerRunner.balancerContext.addressFactory.createSipURI(null, nextNode.getIp());
} else {
// OTHERWISE, a node is already assigned and it's alive
routeSipUri = assignedUri;
}
routeSipUri.setHost(nextNode.getIp());
Integer port = Integer.parseInt(nextNode.getProperties().get(transport + "Port"));
if (port == null) {
throw new RuntimeException("Port is null in the node properties for transport=" + transport);
}
routeSipUri.setPort(port);
routeSipUri.setTransportParam(transport);
routeSipUri.setLrParam();
SipURI uri = (SipURI) request.getRequestURI();
RouteHeader header = (RouteHeader) request.getHeader(RouteHeader.NAME);
if (isHeaderExternal(uri.getHost(), uri.getPort(), ((ViaHeader) request.getHeader("Via")).getTransport(), isIpv6) || header != null) {
final RouteHeader route = balancerRunner.balancerContext.headerFactory.createRouteHeader(balancerRunner.balancerContext.addressFactory.createAddress(routeSipUri));
request.addFirst(route);
// For http://code.google.com/p/mobicents/issues/detail?id=2132
if (originalRouteHeaderUri != null && request.getRequestURI().isSipURI()) {
// we will just compare by hostport id
String rurihostid = uri.getHost() + uri.getPort();
String originalhostid = originalRouteHeaderUri.getHost() + originalRouteHeaderUri.getPort();
if (rurihostid.equals(originalhostid)) {
uri.setPort(routeSipUri.getPort());
uri.setHost(routeSipUri.getHost());
}
}
} else {
// should not add any routes , packet is destinated to lb
uri.setPort(routeSipUri.getPort());
uri.setHost(routeSipUri.getHost());
}
} catch (Exception e) {
throw new RuntimeException("Error adding route header", e);
}
}
} else {
nextNode = ctx.balancerAlgorithm.processAssignedExternalRequest(request, assignedNode);
if (logger.isDebugEnabled()) {
logger.debug("Next node " + nextNode + " from assignedNode " + assignedNode);
}
// add Route header for using it for transferring instead of using uri
if (nextNode != null && hints.subsequentRequest && !isRequestFromServer) {
if (request.getRequestURI().isSipURI()) {
SipURI sipUri = (SipURI) request.getRequestURI();
SipURI routeSipUri = balancerRunner.balancerContext.addressFactory.createSipURI(null, nextNode.getIp());
Integer port = Integer.parseInt(nextNode.getProperties().get(transport + "Port"));
// port should not be null since it subsequent request
if (port != null) {
routeSipUri.setPort(port);
routeSipUri.setTransportParam(transport);
routeSipUri.setLrParam();
if (!sipUri.getHost().equals(routeSipUri.getHost()) || sipUri.getPort() != routeSipUri.getPort()) {
Boolean oldHeaderMatch = false;
Header oldHeader = request.getHeader(RouteHeader.NAME);
if (oldHeader != null) {
RouteHeader oldRouteHeader = (RouteHeader) oldHeader;
if (oldRouteHeader.getAddress().getURI().isSipURI()) {
SipURI oldURI = (SipURI) oldRouteHeader.getAddress().getURI();
if (oldURI.getHost().equals(routeSipUri.getHost()) && oldURI.getPort() == routeSipUri.getPort())
oldHeaderMatch = true;
}
}
if (!oldHeaderMatch) {
final RouteHeader route = balancerRunner.balancerContext.headerFactory.createRouteHeader(balancerRunner.balancerContext.addressFactory.createAddress(routeSipUri));
request.addFirst(route);
}
}
}
}
}
}
if (nextNode == null) {
if (logger.isDebugEnabled()) {
logger.debug("No nodes available");
}
if (!Request.ACK.equalsIgnoreCase(request.getMethod())) {
try {
Response response = balancerRunner.balancerContext.messageFactory.createResponse(Response.SERVER_INTERNAL_ERROR, request);
response.setReasonPhrase("No nodes available");
sipProvider.sendResponse(response);
} catch (Exception e) {
logger.error("Unexpected exception while trying to send the error response for this " + request, e);
}
}
return;
} else {
}
if (balancerRunner.balancerContext.maxRequestNumberWithoutResponse != null && balancerRunner.balancerContext.maxResponseTime != null && !Request.ACK.equalsIgnoreCase(request.getMethod()))
nodeHealthcheck(ctx, nextNode);
}
if (logger.isDebugEnabled()) {
logger.debug("Next node " + nextNode);
}
String requestMethod = request.getMethod();
// https://telestax.atlassian.net/browse/LB-25 improve performance by sending back 100 Trying right away to tame retransmissions.
if (balancerRunner.balancerContext.isSendTrying) {
logger.debug("Load balancer sends 100 TRYING");
if (requestMethod.equals(Request.INVITE) || requestMethod.equals(Request.SUBSCRIBE) || requestMethod.equals(Request.NOTIFY) || requestMethod.equals(Request.MESSAGE) || requestMethod.equals(Request.REFER) || requestMethod.equals(Request.PUBLISH) || requestMethod.equals(Request.UPDATE)) {
try {
Response response = balancerRunner.balancerContext.messageFactory.createResponse(Response.TRYING, request);
RouteList routeList = ((SIPMessage) request).getRouteHeaders();
if (routeList != null) {
Route route = (Route) routeList.getFirst();
SipUri sipUri = (SipUri) route.getAddress().getURI();
if (sipUri.toString().contains("node_host") || sipUri.toString().contains("node_port")) {
String nodeHost = sipUri.getParameter("node_host");
int nodePort = Integer.parseInt(sipUri.getParameter("node_port"));
ViaHeader viaHeader = (ViaHeader) response.getHeader(ViaHeader.NAME);
viaHeader.setHost(nodeHost);
viaHeader.setPort(nodePort);
}
}
sipProvider.sendResponse(response);
} catch (SipException e) {
logger.error("Unexpected exception while sending TRYING", e);
} catch (ParseException e) {
logger.error("Unexpected exception while sending TRYING", e);
} catch (NumberFormatException e) {
logger.error("Unexpected exception while sending TRYING", e);
} catch (InvalidArgumentException e) {
logger.error("Unexpected exception while sending TRYING", e);
}
}
} else {
logger.debug("Load balancer do not send 100 TRYING, this option is disabled");
}
hints.serverAssignedNode = nextNode;
if (!hints.subsequentRequest && dialogCreationMethods.contains(request.getMethod())) {
addLBRecordRoute(sipProvider, request, hints, version, isIpv6);
}
// Stateless proxies must not use internal state or ransom values when creating branch because they
// must repeat exactly the same branches for retransmissions
final ViaHeader via = (ViaHeader) request.getHeader(ViaHeader.NAME);
String newBranch = via.getBranch() + callID.substring(0, Math.min(callID.length(), 5));
// Add the via header to the top of the header list.
ViaHeader viaHeaderExternal = null;
ViaHeader viaHeaderInternal = null;
String externalViaHost = null;
String internalViaHost = null;
String meantHost = null;
if (!isRequestFromServer)
meantHost = ((ViaHeader) request.getHeader(ViaHeader.NAME)).getReceived();
else {
Header routeHeader = request.getHeader(RouteHeader.NAME);
if (routeHeader != null)
meantHost = ((SipURI) ((RouteHeader) routeHeader).getAddress().getURI()).getHost();
}
if (!isIpv6) {
if (balancerRunner.balancerContext.routingRulesIpv4 != null && meantHost != null) {
boolean found = false;
for (RoutingRule rule : balancerRunner.balancerContext.routingRulesIpv4) {
if (rule.getIpPattern().matcher(meantHost).matches() && !rule.isPatch) {
found = true;
externalViaHost = balancerRunner.balancerContext.externalHost;
internalViaHost = balancerRunner.balancerContext.internalHost;
break;
}
}
if (!found) {
externalViaHost = balancerRunner.balancerContext.externalViaHost;
internalViaHost = balancerRunner.balancerContext.internalViaHost;
}
} else {
externalViaHost = balancerRunner.balancerContext.externalViaHost;
internalViaHost = balancerRunner.balancerContext.internalViaHost;
}
} else {
if (balancerRunner.balancerContext.routingRulesIpv6 != null && meantHost != null) {
boolean found = false;
for (RoutingRule rule : balancerRunner.balancerContext.routingRulesIpv6) {
if (rule.getIpPattern().matcher(meantHost).matches() && !rule.isPatch) {
found = true;
externalViaHost = balancerRunner.balancerContext.externalIpv6Host;
internalViaHost = balancerRunner.balancerContext.internalIpv6Host;
break;
}
}
if (!found) {
externalViaHost = balancerRunner.balancerContext.externalIpv6ViaHost;
internalViaHost = balancerRunner.balancerContext.internalIpv6ViaHost;
}
} else {
externalViaHost = balancerRunner.balancerContext.externalIpv6ViaHost;
internalViaHost = balancerRunner.balancerContext.internalIpv6ViaHost;
}
}
if (!isRequestFromServer) {
viaHeaderExternal = balancerRunner.balancerContext.headerFactory.createViaHeader(externalViaHost, balancerRunner.balancerContext.getExternalViaPortByTransport(outerTransport, isIpv6), outerTransport, newBranch + "_" + version);
String innerTransport = transport;
if (balancerRunner.balancerContext.internalTransport != null) {
if (logger.isDebugEnabled()) {
logger.debug("Set internal transport for for creating Via header : " + balancerRunner.balancerContext.internalTransport);
}
innerTransport = balancerRunner.balancerContext.internalTransport;
} else if (balancerRunner.balancerContext.terminateTLSTraffic) {
if (logger.isDebugEnabled()) {
logger.debug("Terminate TLS traffic, isRequestFromServer: " + isRequestFromServer + " transport before " + innerTransport);
}
if (innerTransport.equalsIgnoreCase(ListeningPoint.TLS))
innerTransport = ListeningPoint.TCP;
else if (innerTransport.equalsIgnoreCase(ListeningPointExt.WSS))
innerTransport = ListeningPointExt.WS;
if (logger.isDebugEnabled()) {
logger.debug("Terminate TLS traffic, transport after " + innerTransport);
}
}
if (balancerRunner.balancerContext.isTwoEntrypoints())
viaHeaderInternal = balancerRunner.balancerContext.headerFactory.createViaHeader(internalViaHost, balancerRunner.balancerContext.getInternalViaPortByTransport(innerTransport, isIpv6), innerTransport, newBranch + "zsd" + "_" + version);
else
viaHeaderInternal = balancerRunner.balancerContext.headerFactory.createViaHeader(externalViaHost, balancerRunner.balancerContext.getExternalViaPortByTransport(innerTransport, isIpv6), innerTransport, newBranch + "zsd" + "_" + version);
} else {
if (balancerRunner.balancerContext.isTwoEntrypoints())
viaHeaderInternal = balancerRunner.balancerContext.headerFactory.createViaHeader(internalViaHost, balancerRunner.balancerContext.getInternalViaPortByTransport(transport, isIpv6), transport, newBranch + "zsd" + "_" + version);
else
viaHeaderInternal = balancerRunner.balancerContext.headerFactory.createViaHeader(externalViaHost, balancerRunner.balancerContext.getExternalViaPortByTransport(transport, isIpv6), transport, newBranch + "zsd" + "_" + version);
// https://github.com/RestComm/load-balancer/issues/67
// if (balancerRunner.balancerContext.terminateTLSTraffic) {
// if(logger.isDebugEnabled()) {
// logger.debug("Terminate TLS traffic, isRequestFromServer: " + isRequestFromServer +
// " transport before " + outerTransport);
// }
//
// if (outerTransport.equalsIgnoreCase(ListeningPoint.TCP))
// outerTransport = ListeningPoint.TLS;
// else if (outerTransport.equalsIgnoreCase(ListeningPointExt.WS))
// outerTransport = ListeningPointExt.WSS;
//
// if(logger.isDebugEnabled()) {
// logger.debug("Terminate TLS traffic, transport after " + outerTransport);
// }
// }
viaHeaderExternal = balancerRunner.balancerContext.headerFactory.createViaHeader(externalViaHost, balancerRunner.balancerContext.getExternalViaPortByTransport(outerTransport, isIpv6), outerTransport, newBranch + "_" + version);
}
if (logger.isDebugEnabled()) {
logger.debug("ViaHeaders will be added " + viaHeaderExternal + " and " + viaHeaderInternal);
logger.debug("Sending the request:\n" + request + "\n on the other side");
}
if (getLoopbackUri(request, isIpv6) != null) {
logger.warn("Drop. Cannot forward to loopback the following request: " + request);
return;
}
try {
if (!isRequestFromServer) {
request.addHeader(viaHeaderExternal);
if (viaHeaderInternal != null)
request.addHeader(viaHeaderInternal);
if (balancerRunner.balancerContext.terminateTLSTraffic) {
// https://github.com/RestComm/load-balancer/issues/67
// Patching the contact header for incoming requests so that requests coming out of nodes will use the non secure version
ContactHeader contactHeader = (ContactHeader) request.getHeader(ContactHeader.NAME);
if (contactHeader != null) {
final URI contactURI = contactHeader.getAddress().getURI();
if (logger.isDebugEnabled()) {
logger.debug("Patching the contact header " + contactURI + " so that requests coming out of nodes will use the non secure protocol");
}
if (contactURI instanceof SipUri) {
((SipUri) contactURI).setTransportParam(outerTransport);
logger.debug("new transport " + contactURI + " so that requests coming out of nodes will use the non secure protocol");
}
}
} else if (balancerRunner.balancerContext.internalTransport != null) {
// https://github.com/RestComm/load-balancer/issues/67
// Patching the contact header for incoming requests so that requests coming out of nodes will use the non secure version
ContactHeader contactHeader = (ContactHeader) request.getHeader(ContactHeader.NAME);
if (contactHeader != null) {
final URI contactURI = contactHeader.getAddress().getURI();
if (logger.isDebugEnabled()) {
logger.debug("Patching the contact header " + contactURI + " so that requests coming out of nodes will use correct protocol");
}
if (contactURI instanceof SipUri) {
((SipUri) contactURI).setTransportParam(outerTransport);
logger.debug("new transport " + contactURI + " so that requests coming out of nodes will use correct protocol");
}
}
}
if (logger.isDebugEnabled()) {
logger.debug("Sending the request:\n" + request);
}
if (balancerRunner.balancerContext.isTwoEntrypoints()) {
if (!isIpv6)
balancerRunner.balancerContext.internalSipProvider.sendRequest(request);
else {
balancerRunner.balancerContext.internalIpv6SipProvider.sendRequest(request);
}
} else {
if (!isIpv6)
balancerRunner.balancerContext.externalSipProvider.sendRequest(request);
else
balancerRunner.balancerContext.externalIpv6SipProvider.sendRequest(request);
}
} else {
// Check if the next hop is actually the load balancer again
if (viaHeaderInternal != null)
request.addHeader(viaHeaderInternal);
if (viaHeaderExternal != null)
request.addHeader(viaHeaderExternal);
// }
if (logger.isDebugEnabled()) {
logger.debug("Sending the request:\n" + request);
}
if (!isIpv6)
balancerRunner.balancerContext.externalSipProvider.sendRequest(request);
else
balancerRunner.balancerContext.externalIpv6SipProvider.sendRequest(request);
}
} catch (Exception e) {
if ((request.getMethod().equalsIgnoreCase(Request.OPTIONS) || e.getMessage().equals("Operation not permitted (sendto failed)")) && isRequestFromServer)
logger.warn("Problem with sending OPTIONS to external side possibly due to closed window in broweser");
else
logger.error("Unexpected exception while forwarding the request \n" + request, e);
if (balancerRunner.balancerContext.isSend5xxResponse)
try {
Response response = balancerRunner.balancerContext.messageFactory.createResponse(Response.SERVICE_UNAVAILABLE, request);
response.removeFirst(ViaHeader.NAME);
response.removeFirst(ViaHeader.NAME);
if (balancerRunner.balancerContext.isSend5xxResponseReasonHeader != null) {
HeaderFactory hf = SipFactory.getInstance().createHeaderFactory();
ReasonHeader reasonHeader = hf.createReasonHeader(transport, balancerRunner.balancerContext.isSend5xxResponseSatusCode, balancerRunner.balancerContext.isSend5xxResponseReasonHeader);
response.setHeader(reasonHeader);
}
sipProvider.sendResponse(response);
} catch (SipException ex) {
logger.error("Unexpected exception while sending SERVICE_UNAVAILABLE", ex);
} catch (ParseException ex) {
logger.error("Unexpected exception while sending SERVICE_UNAVAILABLE", ex);
} catch (NumberFormatException ex) {
logger.error("Unexpected exception while sending SERVICE_UNAVAILABLE", ex);
} catch (InvalidArgumentException ex) {
logger.error("Unexpected exception while sending SERVICE_UNAVAILABLE", ex);
}
}
}
use of javax.sip.address.SipURI in project load-balancer by RestComm.
the class Ipv6Test method testInternalTcpRequest.
@Test
public void testInternalTcpRequest() throws Exception {
setUp();
String fromName = "sender";
String fromHost = "sip-servlets.com";
SipURI fromAddress6 = ipv6Server.protocolObjects.addressFactory.createSipURI(fromName, fromHost);
String toUser = "replaces";
String toHost = "sip-servlets.com";
SipURI toAddress6 = ipv6Server.protocolObjects.addressFactory.createSipURI(toUser, toHost);
SipURI ruriIpv6 = ipv6Server.protocolObjects.addressFactory.createSipURI("usera", "[::1]:5034");
ruriIpv6.setLrParam();
SipURI routeIpv6 = ipv6Server.protocolObjects.addressFactory.createSipURI("lbint", "[::1]:5075");
routeIpv6.setParameter("node_host", "::1");
routeIpv6.setParameter("node_port", "4060");
routeIpv6.setTransportParam(ListeningPoint.TCP);
// ipv4
SipURI fromAddress4 = ipv4Server.protocolObjects.addressFactory.createSipURI(fromName, fromHost);
String toUser4 = "replaces";
String toHost4 = "sip-servlets.com";
SipURI toAddress4 = ipv6Server.protocolObjects.addressFactory.createSipURI(toUser4, toHost4);
SipURI ruriIpv4 = ipv6Server.protocolObjects.addressFactory.createSipURI("usera", "127.0.0.1:5033");
ruriIpv4.setLrParam();
SipURI routeIpv4 = ipv6Server.protocolObjects.addressFactory.createSipURI("lbint", "127.0.0.1:5065");
routeIpv4.setParameter("node_host", "127.0.0.1");
routeIpv4.setParameter("node_port", "4061");
routeIpv4.setTransportParam(ListeningPoint.TCP);
routeIpv4.setLrParam();
shootistipv4.start();
shootistipv6.start();
ipv4Server.sipListener.sendSipRequest("INVITE", fromAddress4, toAddress4, null, routeIpv4, false, null, null, ruriIpv4);
ipv6Server.sipListener.sendSipRequest("INVITE", fromAddress6, toAddress6, null, routeIpv6, false, null, null, ruriIpv6);
Thread.sleep(10000);
}
Aggregations