use of javax.sip.header.ViaHeader in project XobotOS by xamarin.
the class SipHelper method createViaHeaders.
private List<ViaHeader> createViaHeaders() throws ParseException, SipException {
List<ViaHeader> viaHeaders = new ArrayList<ViaHeader>(1);
ListeningPoint lp = getListeningPoint();
ViaHeader viaHeader = mHeaderFactory.createViaHeader(lp.getIPAddress(), lp.getPort(), lp.getTransport(), null);
viaHeader.setRPort();
viaHeaders.add(viaHeader);
return viaHeaders;
}
use of javax.sip.header.ViaHeader in project load-balancer by RestComm.
the class SIPBalancerForwarder method addLBRecordRoute.
/**
* @param sipProvider
* @param request
* @param hints
* @throws ParseException
*/
private void addLBRecordRoute(SipProvider sipProvider, Request request, RouteHeaderHints hints, String version, boolean isIpv6) throws ParseException {
if (logger.isDebugEnabled()) {
if (!isIpv6)
logger.debug("adding Record Router Header :" + balancerRunner.balancerContext.activeExternalHeader);
else
logger.debug("adding IPv6 Record Router Header :" + Arrays.toString(balancerRunner.balancerContext.activeExternalIpv6Header));
}
String transport = ((ViaHeader) request.getHeader(ViaHeader.NAME)).getTransport().toLowerCase();
if (sipProvider.equals(balancerRunner.balancerContext.externalSipProvider) || sipProvider.equals(balancerRunner.balancerContext.externalIpv6SipProvider)) {
int transportIndex = 0;
int internalTransportIndex = 0;
if (balancerRunner.balancerContext.internalTransport != null) {
if (logger.isDebugEnabled()) {
logger.debug("Set internal transport for adding Record Route): " + balancerRunner.balancerContext.internalTransport);
}
String currExternalTransport = transport.toUpperCase();
switch(currExternalTransport) {
case ListeningPoint.UDP:
transportIndex = UDP;
break;
case ListeningPoint.TCP:
transportIndex = TCP;
break;
case ListeningPoint.TLS:
transportIndex = TLS;
break;
case ListeningPointExt.WS:
transportIndex = WS;
break;
case ListeningPointExt.WSS:
transportIndex = WSS;
break;
}
String currInternalTransport = balancerRunner.balancerContext.internalTransport.toUpperCase();
switch(currInternalTransport) {
case ListeningPoint.UDP:
internalTransportIndex = UDP;
break;
case ListeningPoint.TCP:
internalTransportIndex = TCP;
break;
case ListeningPoint.TLS:
internalTransportIndex = TLS;
break;
case ListeningPointExt.WS:
internalTransportIndex = WS;
break;
case ListeningPointExt.WSS:
internalTransportIndex = WSS;
break;
}
} else {
transportIndex = TLS;
internalTransportIndex = TLS;
if (balancerRunner.balancerContext.terminateTLSTraffic) {
internalTransportIndex = TCP;
}
if (transport.equalsIgnoreCase(ListeningPoint.UDP)) {
transportIndex = UDP;
internalTransportIndex = UDP;
} else if (transport.equalsIgnoreCase(ListeningPoint.TCP)) {
transportIndex = TCP;
internalTransportIndex = TCP;
} else if (transport.equalsIgnoreCase(ListeningPointExt.WS)) {
transportIndex = WS;
internalTransportIndex = WS;
} else if (transport.equalsIgnoreCase(ListeningPointExt.WSS)) {
transportIndex = WSS;
if (balancerRunner.balancerContext.terminateTLSTraffic) {
internalTransportIndex = WS;
} else {
internalTransportIndex = WSS;
}
}
}
// comes from client
String received = ((ViaHeader) request.getHeader(ViaHeader.NAME)).getReceived();
RecordRouteHeader currExternalRR = null;
RecordRouteHeader currInternalRR = null;
if (!isIpv6) {
if (balancerRunner.balancerContext.routingRulesIpv4 != null && received != null) {
boolean found = false;
for (RoutingRule rule : balancerRunner.balancerContext.routingRulesIpv4) {
if (rule.getIpPattern().matcher(received).matches() && !rule.isPatch) {
found = true;
currExternalRR = balancerRunner.balancerContext.activePrivateExternalHeader[transportIndex];
currInternalRR = balancerRunner.balancerContext.activePrivateInternalHeader[internalTransportIndex];
break;
}
}
if (!found) {
currExternalRR = balancerRunner.balancerContext.activeExternalHeader[transportIndex];
currInternalRR = balancerRunner.balancerContext.activeInternalHeader[internalTransportIndex];
}
} else {
currExternalRR = balancerRunner.balancerContext.activeExternalHeader[transportIndex];
currInternalRR = balancerRunner.balancerContext.activeInternalHeader[internalTransportIndex];
}
} else {
if (balancerRunner.balancerContext.routingRulesIpv6 != null && received != null) {
boolean found = false;
for (RoutingRule rule : balancerRunner.balancerContext.routingRulesIpv6) {
if (rule.getIpPattern().matcher(received).matches() && !rule.isPatch) {
found = true;
currExternalRR = balancerRunner.balancerContext.activePrivateExternalIpv6Header[transportIndex];
currInternalRR = balancerRunner.balancerContext.activePrivateInternalIpv6Header[internalTransportIndex];
break;
}
}
if (!found) {
currExternalRR = balancerRunner.balancerContext.activeExternalIpv6Header[transportIndex];
currInternalRR = balancerRunner.balancerContext.activeInternalIpv6Header[internalTransportIndex];
}
} else {
currExternalRR = balancerRunner.balancerContext.activeExternalIpv6Header[transportIndex];
currInternalRR = balancerRunner.balancerContext.activeInternalIpv6Header[internalTransportIndex];
}
}
addTwoRecordRoutes(request, currExternalRR, currInternalRR, hints, getTransportById(internalTransportIndex));
} else {
int transportIndex = TLS;
int externalTransportIndex = TLS;
String externalTransport = transport;
URI requestURI = ((Request) request).getRequestURI();
if (requestURI.isSipURI()) {
if (((SipUri) requestURI).getTransportParam() != null)
externalTransport = ((SipUri) requestURI).getTransportParam();
}
if (transport.equalsIgnoreCase(ListeningPoint.UDP))
transportIndex = UDP;
else if (transport.equalsIgnoreCase(ListeningPoint.TCP))
transportIndex = TCP;
else if (transport.equalsIgnoreCase(ListeningPointExt.WS))
transportIndex = WS;
else if (transport.equalsIgnoreCase(ListeningPointExt.WSS))
transportIndex = WSS;
if (externalTransport.equalsIgnoreCase(ListeningPoint.UDP))
externalTransportIndex = UDP;
else if (externalTransport.equalsIgnoreCase(ListeningPoint.TCP))
externalTransportIndex = TCP;
else if (externalTransport.equalsIgnoreCase(ListeningPointExt.WS))
externalTransportIndex = WS;
else if (externalTransport.equalsIgnoreCase(ListeningPointExt.WSS))
externalTransportIndex = WSS;
// comes from app server
Header routeHeader = request.getHeader(RouteHeader.NAME);
String routeHost = null;
if (routeHeader != null)
routeHost = ((SipURI) ((RouteHeader) routeHeader).getAddress().getURI()).getHost();
RecordRouteHeader currExternalRR = null;
RecordRouteHeader currInternalRR = null;
if (!isIpv6) {
if (balancerRunner.balancerContext.routingRulesIpv4 != null && routeHost != null) {
boolean found = false;
for (RoutingRule rule : balancerRunner.balancerContext.routingRulesIpv4) {
if (rule.getIpPattern().matcher(routeHost).matches() && !rule.isPatch) {
found = true;
currExternalRR = balancerRunner.balancerContext.activePrivateExternalHeader[externalTransportIndex];
currInternalRR = balancerRunner.balancerContext.activePrivateInternalHeader[transportIndex];
break;
}
}
if (!found) {
currExternalRR = balancerRunner.balancerContext.activeExternalHeader[externalTransportIndex];
currInternalRR = balancerRunner.balancerContext.activeInternalHeader[transportIndex];
}
} else {
currExternalRR = balancerRunner.balancerContext.activeExternalHeader[externalTransportIndex];
currInternalRR = balancerRunner.balancerContext.activeInternalHeader[transportIndex];
}
} else {
if (balancerRunner.balancerContext.routingRulesIpv6 != null && routeHost != null) {
boolean found = false;
for (RoutingRule rule : balancerRunner.balancerContext.routingRulesIpv6) {
if (rule.getIpPattern().matcher(routeHost).matches() && !rule.isPatch) {
found = true;
currExternalRR = balancerRunner.balancerContext.activePrivateExternalIpv6Header[externalTransportIndex];
currInternalRR = balancerRunner.balancerContext.activePrivateInternalIpv6Header[transportIndex];
break;
}
}
if (!found) {
currExternalRR = balancerRunner.balancerContext.activeExternalIpv6Header[externalTransportIndex];
currInternalRR = balancerRunner.balancerContext.activeInternalIpv6Header[transportIndex];
}
} else {
currExternalRR = balancerRunner.balancerContext.activeExternalIpv6Header[externalTransportIndex];
currInternalRR = balancerRunner.balancerContext.activeInternalIpv6Header[transportIndex];
}
}
addTwoRecordRoutes(request, currInternalRR, currExternalRR, hints, getTransportById(transportIndex));
if (logger.isInfoEnabled()) {
logger.info("Will patch Request : \"" + request.getRequestURI() + "\" to provide public IP address for the RecordRoute header");
}
patchSipMessageForNAT(request, isIpv6);
}
}
use of javax.sip.header.ViaHeader in project load-balancer by RestComm.
the class SIPBalancerForwarder method processResponse.
/**
* @param originalRequest
* @param serverTransaction
* @throws ParseException
* @throws SipException
* @throws InvalidArgumentException
* @throws TransactionUnavailableException
*/
/*
* (non-Javadoc)
* @see javax.sip.SipListener#processResponse(javax.sip.ResponseEvent)
*/
public void processResponse(ResponseEvent responseEvent) {
BalancerAppContent content = (BalancerAppContent) responseEvent.getSource();
boolean isIpv6 = content.isIpv6();
SipProvider sipProvider = content.getProvider();
Response originalResponse = responseEvent.getResponse();
if (logger.isDebugEnabled()) {
logger.debug("got response :\n" + originalResponse);
}
updateStats(originalResponse);
final Response response = (Response) originalResponse;
Node senderNode = getSenderNode(response);
if (senderNode != null) {
if (logger.isDebugEnabled()) {
logger.debug("Updating Timestamp of sendernode: " + senderNode);
}
senderNode.updateTimerStamp();
}
// Topmost via headers is me. As it is response to external request
ViaHeader viaHeader = (ViaHeader) response.getHeader(ViaHeader.NAME);
String branch = viaHeader.getBranch();
int versionDelimiter = branch.lastIndexOf('_');
String version = branch.substring(versionDelimiter + 1);
InvocationContext ctx = balancerRunner.getInvocationContext(version);
if (viaHeader != null && !isHeaderExternal(viaHeader.getHost(), viaHeader.getPort(), viaHeader.getTransport(), isIpv6)) {
response.removeFirst(ViaHeader.NAME);
}
viaHeader = (ViaHeader) response.getHeader(ViaHeader.NAME);
String transport = viaHeader.getTransport();
if (viaHeader != null && !isHeaderExternal(viaHeader.getHost(), viaHeader.getPort(), viaHeader.getTransport(), isIpv6)) {
response.removeFirst(ViaHeader.NAME);
}
boolean fromServer = false;
if (balancerRunner.balancerContext.isTwoEntrypoints()) {
if (!isIpv6)
fromServer = sipProvider.equals(balancerRunner.balancerContext.internalSipProvider);
else
fromServer = sipProvider.equals(balancerRunner.balancerContext.internalIpv6SipProvider);
if (logger.isDebugEnabled()) {
if (!isIpv6)
logger.debug("fromServer : " + fromServer + ", sipProvider " + sipProvider + ", internalSipProvider " + balancerRunner.balancerContext.internalSipProvider);
else
logger.debug("fromServer : " + fromServer + ", sipProvider " + sipProvider + ", internalIpv6SipProvider " + balancerRunner.balancerContext.internalIpv6SipProvider);
}
} else {
fromServer = senderNode == null;
if (logger.isDebugEnabled()) {
logger.debug("fromServer : " + fromServer + ", senderNode " + senderNode);
}
}
// only for external responses
if (balancerRunner.balancerContext.isUseWithNexmo && !fromServer) {
viaHeader = (ViaHeader) response.getHeader(ViaHeader.NAME);
if (viaHeader != null) {
if (logger.isDebugEnabled())
logger.debug("We are going to remove rport and received parametres from :" + viaHeader + " from external response");
response.removeFirst(ViaHeader.NAME);
viaHeader.removeParameter("rport");
viaHeader.removeParameter("received");
try {
response.addFirst(viaHeader);
} catch (NullPointerException | SipException e) {
e.printStackTrace();
}
if (logger.isDebugEnabled())
logger.debug("After removing :" + response);
}
}
if (fromServer) {
if (senderNode != null && senderNode.getIp() != null) {
if (balancerRunner.balancerContext.maxRequestNumberWithoutResponse != null && balancerRunner.balancerContext.maxResponseTime != null) {
KeySip keySip = new KeySip(senderNode, isIpv6);
// adding null check for https://github.com/RestComm/load-balancer/issues/83
Node currNode = ctx.sipNodeMap(isIpv6).get(keySip);
if (currNode != null) {
if (logger.isDebugEnabled())
logger.debug("We are going to reset counters of health check" + currNode.getRequestNumberWithoutResponse() + " : " + currNode.getLastTimeResponse());
currNode.setLastTimeResponse(System.currentTimeMillis());
currNode.setRequestNumberWithoutResponse(0);
if (logger.isDebugEnabled())
logger.debug("Counter of request without responses is : " + currNode.getRequestNumberWithoutResponse() + " : " + currNode.getLastTimeResponse());
} else {
logger.warn("Node is null, we will not reset counters");
}
}
mediaFailureDetection(response, ctx, senderNode);
}
/*
if("true".equals(balancerRunner.balancerContext.properties.getProperty("removeNodesOn500Response")) && response.getStatusCode() == 500) {
// If the server is broken remove it from the list and try another one with the next retransmission
if(!(sourceNode instanceof ExtraServerNode)) {
if(balancerRunner.balancerContext.nodes.size()>1) {
balancerRunner.balancerContext.nodes.remove(sourceNode);
balancerRunner.balancerContext.balancerAlgorithm.nodeRemoved(sourceNode);
}
}
}
*/
String publicIp = null;
if (!isIpv6)
publicIp = balancerRunner.balancerContext.publicIP;
else
publicIp = balancerRunner.balancerContext.publicIPv6;
if (publicIp != null && publicIp.trim().length() > 0) {
if (logger.isDebugEnabled()) {
logger.debug("Will add Record-Route header to response with public IP Address: " + publicIp);
}
patchSipMessageForNAT(response, isIpv6);
}
// https://github.com/RestComm/load-balancer/issues/45 Adding sender node for the algorithm to be available
((ResponseExt) response).setApplicationData(senderNode);
ctx.balancerAlgorithm.processInternalResponse(response, isIpv6);
try {
if (logger.isDebugEnabled()) {
logger.debug("from server sending response externally " + response);
}
if (!isIpv6)
balancerRunner.balancerContext.externalSipProvider.sendResponse(response);
else
balancerRunner.balancerContext.externalIpv6SipProvider.sendResponse(response);
} catch (Exception ex) {
logger.error("Unexpected exception while forwarding the response \n" + response, ex);
}
} else {
try {
SIPMessage message = (SIPMessage) response;
String initialRemoteAddr = message.getPeerPacketSourceAddress().getHostAddress();
String initialRemotePort = String.valueOf(message.getPeerPacketSourcePort());
Header remoteAddrHeader = null;
Header remotePortHeader = null;
try {
HeaderFactory hf = SipFactory.getInstance().createHeaderFactory();
remoteAddrHeader = hf.createHeader("X-Sip-Balancer-InitialRemoteAddr", initialRemoteAddr);
remotePortHeader = hf.createHeader("X-Sip-Balancer-InitialRemotePort", initialRemotePort);
} catch (PeerUnavailableException e) {
logger.error("Unexpected exception while creating custom headers for REGISTER message ", e);
} catch (ParseException e) {
logger.error("Unexpected exception while creating custom headers for REGISTER message ", e);
}
if (remoteAddrHeader != null)
response.addHeader(remoteAddrHeader);
if (remotePortHeader != null)
response.addHeader(remotePortHeader);
if (balancerRunner.balancerContext.isTwoEntrypoints()) {
ctx.balancerAlgorithm.processExternalResponse(response, isIpv6);
if (logger.isDebugEnabled()) {
logger.debug("two entry points: from external sending response " + response);
}
if (!isIpv6)
balancerRunner.balancerContext.internalSipProvider.sendResponse(response);
else
balancerRunner.balancerContext.internalIpv6SipProvider.sendResponse(response);
} else {
if (!comesFromInternalNode(response, ctx, initialRemoteAddr, message.getPeerPacketSourcePort(), transport, isIpv6))
ctx.balancerAlgorithm.processExternalResponse(response, isIpv6);
else
ctx.balancerAlgorithm.processInternalResponse(response, isIpv6);
if (logger.isDebugEnabled()) {
logger.debug("one entry point: from external sending response " + response);
}
if (!isIpv6)
balancerRunner.balancerContext.externalSipProvider.sendResponse(response);
else
balancerRunner.balancerContext.externalIpv6SipProvider.sendResponse(response);
}
} catch (Exception ex) {
logger.error("Unexpected exception while forwarding the response \n" + response, ex);
}
}
}
use of javax.sip.header.ViaHeader 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.header.ViaHeader 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;
}
Aggregations