use of javax.sip.TransactionUnavailableException in project XobotOS by xamarin.
the class SipProviderImpl method getNewClientTransaction.
/*
* (non-Javadoc)
*
* @see javax.sip.SipProvider#getNewClientTransaction(javax.sip.message.Request)
*/
public ClientTransaction getNewClientTransaction(Request request) throws TransactionUnavailableException {
if (request == null)
throw new NullPointerException("null request");
if (!sipStack.isAlive())
throw new TransactionUnavailableException("Stack is stopped");
SIPRequest sipRequest = (SIPRequest) request;
if (sipRequest.getTransaction() != null)
throw new TransactionUnavailableException("Transaction already assigned to request");
if (sipRequest.getMethod().equals(Request.ACK)) {
throw new TransactionUnavailableException("Cannot create client transaction for " + Request.ACK);
}
// sloppy
if (sipRequest.getTopmostVia() == null) {
ListeningPointImpl lp = (ListeningPointImpl) this.getListeningPoint("udp");
Via via = lp.getViaHeader();
request.setHeader(via);
}
// Give the request a quick check to see if all headers are assigned.
try {
sipRequest.checkHeaders();
} catch (ParseException ex) {
throw new TransactionUnavailableException(ex.getMessage(), ex);
}
/*
* User decided to give us his own via header branch. Lets see if it
* results in a clash. If so reject the request.
*/
if (sipRequest.getTopmostVia().getBranch() != null && sipRequest.getTopmostVia().getBranch().startsWith(SIPConstants.BRANCH_MAGIC_COOKIE) && sipStack.findTransaction((SIPRequest) request, false) != null) {
throw new TransactionUnavailableException("Transaction already exists!");
}
if (request.getMethod().equalsIgnoreCase(Request.CANCEL)) {
SIPClientTransaction ct = (SIPClientTransaction) sipStack.findCancelTransaction((SIPRequest) request, false);
if (ct != null) {
ClientTransaction retval = sipStack.createClientTransaction((SIPRequest) request, ct.getMessageChannel());
((SIPTransaction) retval).addEventListener(this);
sipStack.addTransaction((SIPClientTransaction) retval);
if (ct.getDialog() != null) {
((SIPClientTransaction) retval).setDialog((SIPDialog) ct.getDialog(), sipRequest.getDialogId(false));
}
return retval;
}
}
if (sipStack.isLoggingEnabled())
sipStack.getStackLogger().logDebug("could not find existing transaction for " + ((SIPRequest) request).getFirstLine() + " creating a new one ");
// Could not find a dialog or the route is not set in dialog.
Hop hop = null;
try {
hop = sipStack.getNextHop((SIPRequest) request);
if (hop == null)
throw new TransactionUnavailableException("Cannot resolve next hop -- transaction unavailable");
} catch (SipException ex) {
throw new TransactionUnavailableException("Cannot resolve next hop -- transaction unavailable", ex);
}
String transport = hop.getTransport();
ListeningPointImpl listeningPoint = (ListeningPointImpl) this.getListeningPoint(transport);
String dialogId = sipRequest.getDialogId(false);
SIPDialog dialog = sipStack.getDialog(dialogId);
if (dialog != null && dialog.getState() == DialogState.TERMINATED) {
// throw new TransactionUnavailableException
// ("Found a terminated dialog -- possible re-use of old tag
// parameters");
sipStack.removeDialog(dialog);
}
try {
// Set the brannch id before you ask for a tx.
// If the user has set his own branch Id and the
// branch id starts with a valid prefix, then take it.
// otherwise, generate one. If branch ID checking has
// been requested, set the branch ID.
String branchId = null;
if (sipRequest.getTopmostVia().getBranch() == null || !sipRequest.getTopmostVia().getBranch().startsWith(SIPConstants.BRANCH_MAGIC_COOKIE) || sipStack.checkBranchId()) {
branchId = Utils.getInstance().generateBranchId();
sipRequest.getTopmostVia().setBranch(branchId);
}
Via topmostVia = sipRequest.getTopmostVia();
//set port and transport if user hasn't already done this.
if (topmostVia.getTransport() == null)
topmostVia.setTransport(transport);
if (topmostVia.getPort() == -1)
topmostVia.setPort(listeningPoint.getPort());
branchId = sipRequest.getTopmostVia().getBranch();
SIPClientTransaction ct = (SIPClientTransaction) sipStack.createMessageChannel(sipRequest, listeningPoint.getMessageProcessor(), hop);
if (ct == null)
throw new TransactionUnavailableException("Cound not create tx");
ct.setNextHop(hop);
ct.setOriginalRequest(sipRequest);
ct.setBranch(branchId);
// if the stack supports dialogs then
if (sipStack.isDialogCreated(request.getMethod())) {
// (but noticed by Brad Templeton)
if (dialog != null)
ct.setDialog(dialog, sipRequest.getDialogId(false));
else if (this.isAutomaticDialogSupportEnabled()) {
SIPDialog sipDialog = sipStack.createDialog(ct);
ct.setDialog(sipDialog, sipRequest.getDialogId(false));
}
} else {
if (dialog != null) {
ct.setDialog(dialog, sipRequest.getDialogId(false));
}
}
// The provider is the event listener for all transactions.
ct.addEventListener(this);
return (ClientTransaction) ct;
} catch (IOException ex) {
throw new TransactionUnavailableException("Could not resolve next hop or listening point unavailable! ", ex);
} catch (java.text.ParseException ex) {
InternalErrorHandler.handleException(ex);
throw new TransactionUnavailableException("Unexpected Exception FIXME! ", ex);
} catch (InvalidArgumentException ex) {
InternalErrorHandler.handleException(ex);
throw new TransactionUnavailableException("Unexpected Exception FIXME! ", ex);
}
}
use of javax.sip.TransactionUnavailableException 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.TransactionUnavailableException 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.TransactionUnavailableException in project load-balancer by RestComm.
the class Shootist method processRequest.
public void processRequest(RequestEvent requestReceivedEvent) {
Request request = requestReceivedEvent.getRequest();
requests.add(request);
ServerTransaction serverTransactionId = requestReceivedEvent.getServerTransaction();
if (serverTransactionId == null) {
try {
serverTransactionId = sipProvider.getNewServerTransaction(request);
} catch (TransactionAlreadyExistsException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (TransactionUnavailableException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
System.out.println("\n\nRequest " + request.getMethod() + " received at " + sipStack.getStackName() + " with server transaction id " + serverTransactionId);
if (request.getMethod().equals(Request.INVITE)) {
processInvite(request, serverTransactionId);
} else if (request.getMethod().equals(Request.BYE)) {
processBye(request, serverTransactionId);
} else if (request.getMethod().equals(Request.ACK)) {
processAck(request, serverTransactionId);
} else {
try {
serverTransactionId.sendResponse(messageFactory.createResponse(200, request));
} catch (Exception e) {
e.printStackTrace();
fail("Unxepcted exception ");
}
}
}
use of javax.sip.TransactionUnavailableException in project load-balancer by RestComm.
the class Shootist method processRequest.
public void processRequest(RequestEvent requestReceivedEvent) {
Request request = requestReceivedEvent.getRequest();
ServerTransaction serverTransactionId = requestReceivedEvent.getServerTransaction();
if (serverTransactionId == null) {
try {
serverTransactionId = sipProvider.getNewServerTransaction(request);
} catch (TransactionAlreadyExistsException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (TransactionUnavailableException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
System.out.println("\n\nRequest " + request.getMethod() + " received at " + sipStack.getStackName() + " with server transaction id " + serverTransactionId);
if (request.getMethod().equals(Request.INVITE)) {
processInvite(request, serverTransactionId);
} else if (request.getMethod().equals(Request.BYE)) {
processBye(request, serverTransactionId);
} else if (request.getMethod().equals(Request.ACK)) {
processAck(request, serverTransactionId);
} else {
try {
serverTransactionId.sendResponse(messageFactory.createResponse(200, request));
} catch (Exception e) {
e.printStackTrace();
fail("Unxepcted exception ");
}
}
}
Aggregations