use of javax.sip.address.Hop in project XobotOS by xamarin.
the class SIPServerTransaction method sendResponse.
/**
* Send a response.
*
* @param transactionResponse -- the response to send
*
*/
private void sendResponse(SIPResponse transactionResponse) throws IOException {
try {
// that created the transaction, if that connection is still open.
if (isReliable()) {
getMessageChannel().sendMessage(transactionResponse);
// TODO If that connection attempt fails, the server SHOULD
// use SRV 3263 procedures
// for servers in order to determine the IP address
// and port to open the connection and send the response to.
} else {
Via via = transactionResponse.getTopmostVia();
String transport = via.getTransport();
if (transport == null)
throw new IOException("missing transport!");
// @@@ hagai Symmetric NAT support
int port = via.getRPort();
if (port == -1)
port = via.getPort();
if (port == -1) {
if (transport.equalsIgnoreCase("TLS"))
port = 5061;
else
port = 5060;
}
// Otherwise, if the Via header field value contains a
// "maddr" parameter, the response MUST be forwarded to
// the address listed there, using the port indicated in
// "sent-by",
// or port 5060 if none is present. If the address is a
// multicast
// address, the response SHOULD be sent using
// the TTL indicated in the "ttl" parameter, or with a
// TTL of 1 if that parameter is not present.
String host = null;
if (via.getMAddr() != null) {
host = via.getMAddr();
} else {
// Otherwise (for unreliable unicast transports),
// if the top Via has a "received" parameter, the response
// MUST
// be sent to the
// address in the "received" parameter, using the port
// indicated
// in the
// "sent-by" value, or using port 5060 if none is specified
// explicitly.
host = via.getParameter(Via.RECEIVED);
if (host == null) {
// Otherwise, if it is not receiver-tagged, the response
// MUST be
// sent to the address indicated by the "sent-by" value,
// using the procedures in Section 5
// RFC 3263 PROCEDURE TO BE DONE HERE
host = via.getHost();
}
}
Hop hop = sipStack.addressResolver.resolveAddress(new HopImpl(host, port, transport));
MessageChannel messageChannel = ((SIPTransactionStack) getSIPStack()).createRawMessageChannel(this.getSipProvider().getListeningPoint(hop.getTransport()).getIPAddress(), this.getPort(), hop);
if (messageChannel != null)
messageChannel.sendMessage(transactionResponse);
else
throw new IOException("Could not create a message channel for " + hop);
}
} finally {
this.startTransactionTimer();
}
}
use of javax.sip.address.Hop in project XobotOS by xamarin.
the class SIPDialog method sendRequest.
public void sendRequest(ClientTransaction clientTransactionId, boolean allowInterleaving) throws TransactionDoesNotExistException, SipException {
if ((!allowInterleaving) && clientTransactionId.getRequest().getMethod().equals(Request.INVITE)) {
new Thread((new ReInviteSender(clientTransactionId))).start();
return;
}
SIPRequest dialogRequest = ((SIPClientTransaction) clientTransactionId).getOriginalRequest();
if (sipStack.isLoggingEnabled())
sipStack.getStackLogger().logDebug("dialog.sendRequest " + " dialog = " + this + "\ndialogRequest = \n" + dialogRequest);
if (clientTransactionId == null)
throw new NullPointerException("null parameter");
if (dialogRequest.getMethod().equals(Request.ACK) || dialogRequest.getMethod().equals(Request.CANCEL))
throw new SipException("Bad Request Method. " + dialogRequest.getMethod());
// JvB: added, allow re-sending of BYE after challenge
if (byeSent && isTerminatedOnBye() && !dialogRequest.getMethod().equals(Request.BYE)) {
if (sipStack.isLoggingEnabled())
sipStack.getStackLogger().logError("BYE already sent for " + this);
throw new SipException("Cannot send request; BYE already sent");
}
if (dialogRequest.getTopmostVia() == null) {
Via via = ((SIPClientTransaction) clientTransactionId).getOutgoingViaHeader();
dialogRequest.addHeader(via);
}
if (!this.getCallId().getCallId().equalsIgnoreCase(dialogRequest.getCallId().getCallId())) {
if (sipStack.isLoggingEnabled()) {
sipStack.getStackLogger().logError("CallID " + this.getCallId());
sipStack.getStackLogger().logError("RequestCallID = " + dialogRequest.getCallId().getCallId());
sipStack.getStackLogger().logError("dialog = " + this);
}
throw new SipException("Bad call ID in request");
}
// Set the dialog back pointer.
((SIPClientTransaction) clientTransactionId).setDialog(this, this.dialogId);
this.addTransaction((SIPTransaction) clientTransactionId);
// Enable the retransmission filter for the transaction
((SIPClientTransaction) clientTransactionId).isMapped = true;
From from = (From) dialogRequest.getFrom();
To to = (To) dialogRequest.getTo();
// tag assignment is OK.
if (this.getLocalTag() != null && from.getTag() != null && !from.getTag().equals(this.getLocalTag()))
throw new SipException("From tag mismatch expecting " + this.getLocalTag());
if (this.getRemoteTag() != null && to.getTag() != null && !to.getTag().equals(this.getRemoteTag())) {
if (sipStack.isLoggingEnabled())
this.sipStack.getStackLogger().logWarning("To header tag mismatch expecting " + this.getRemoteTag());
}
/*
* The application is sending a NOTIFY before sending the response of the dialog.
*/
if (this.getLocalTag() == null && dialogRequest.getMethod().equals(Request.NOTIFY)) {
if (!this.getMethod().equals(Request.SUBSCRIBE))
throw new SipException("Trying to send NOTIFY without SUBSCRIBE Dialog!");
this.setLocalTag(from.getTag());
}
try {
if (this.getLocalTag() != null)
from.setTag(this.getLocalTag());
if (this.getRemoteTag() != null)
to.setTag(this.getRemoteTag());
} catch (ParseException ex) {
InternalErrorHandler.handleException(ex);
}
Hop hop = ((SIPClientTransaction) clientTransactionId).getNextHop();
if (sipStack.isLoggingEnabled()) {
sipStack.getStackLogger().logDebug("Using hop = " + hop.getHost() + " : " + hop.getPort());
}
try {
MessageChannel messageChannel = sipStack.createRawMessageChannel(this.getSipProvider().getListeningPoint(hop.getTransport()).getIPAddress(), this.firstTransactionPort, hop);
MessageChannel oldChannel = ((SIPClientTransaction) clientTransactionId).getMessageChannel();
// Remove this from the connection cache if it is in the
// connection
// cache and is not yet active.
oldChannel.uncache();
// Not configured to cache client connections.
if (!sipStack.cacheClientConnections) {
oldChannel.useCount--;
if (sipStack.isLoggingEnabled())
sipStack.getStackLogger().logDebug("oldChannel: useCount " + oldChannel.useCount);
}
if (messageChannel == null) {
/*
* At this point the procedures of 8.1.2 and 12.2.1.1 of RFC3261 have been tried
* but the resulting next hop cannot be resolved (recall that the exception thrown
* is caught and ignored in SIPStack.createMessageChannel() so we end up here with
* a null messageChannel instead of the exception handler below). All else
* failing, try the outbound proxy in accordance with 8.1.2, in particular: This
* ensures that outbound proxies that do not add Record-Route header field values
* will drop out of the path of subsequent requests. It allows endpoints that
* cannot resolve the first Route URI to delegate that task to an outbound proxy.
*
* if one considers the 'first Route URI' of a request constructed according to
* 12.2.1.1 to be the request URI when the route set is empty.
*/
if (sipStack.isLoggingEnabled())
sipStack.getStackLogger().logDebug("Null message channel using outbound proxy !");
Hop outboundProxy = sipStack.getRouter(dialogRequest).getOutboundProxy();
if (outboundProxy == null)
throw new SipException("No route found! hop=" + hop);
messageChannel = sipStack.createRawMessageChannel(this.getSipProvider().getListeningPoint(outboundProxy.getTransport()).getIPAddress(), this.firstTransactionPort, outboundProxy);
if (messageChannel != null)
((SIPClientTransaction) clientTransactionId).setEncapsulatedChannel(messageChannel);
} else {
((SIPClientTransaction) clientTransactionId).setEncapsulatedChannel(messageChannel);
if (sipStack.isLoggingEnabled()) {
sipStack.getStackLogger().logDebug("using message channel " + messageChannel);
}
}
if (messageChannel != null)
messageChannel.useCount++;
// See if we need to release the previously mapped channel.
if ((!sipStack.cacheClientConnections) && oldChannel != null && oldChannel.useCount <= 0)
oldChannel.close();
} catch (Exception ex) {
if (sipStack.isLoggingEnabled())
sipStack.getStackLogger().logException(ex);
throw new SipException("Could not create message channel", ex);
}
try {
// Increment before setting!!
localSequenceNumber++;
dialogRequest.getCSeq().setSeqNumber(getLocalSeqNumber());
} catch (InvalidArgumentException ex) {
sipStack.getStackLogger().logFatalError(ex.getMessage());
}
try {
((SIPClientTransaction) clientTransactionId).sendMessage(dialogRequest);
/*
* Note that if the BYE is rejected then the Dialog should bo back to the ESTABLISHED
* state so we only set state after successful send.
*/
if (dialogRequest.getMethod().equals(Request.BYE)) {
this.byeSent = true;
/*
* Dialog goes into TERMINATED state as soon as BYE is sent. ISSUE 182.
*/
if (isTerminatedOnBye()) {
this.setState(DialogState._TERMINATED);
}
}
} catch (IOException ex) {
throw new SipException("error sending message", ex);
}
}
use of javax.sip.address.Hop in project Openfire by igniterealtime.
the class SipCommRouter method getNextHops.
/**
* Return the default address to forward the request to. The list is
* organized in the following priority.
* <p/>
* If the outboung proxy has been specified, then it is used to construct
* the first element of the list.
* <p/>
* If the requestURI refers directly to a host, the host and port
* information are extracted from it and made the next hop on the list.
*
* @param sipRequest is the sip request to route.
*/
public ListIterator<Hop> getNextHops(Request sipRequest) {
URI requestURI = sipRequest.getRequestURI();
if (requestURI == null) {
throw new IllegalArgumentException("Bad message: Null requestURI");
}
LinkedList<Hop> hops = new LinkedList<Hop>();
if (outboundProxy != null) {
hops.add(outboundProxy);
}
ListIterator routes = sipRequest.getHeaders(RouteHeader.NAME);
if (routes != null && routes.hasNext()) {
while (routes.hasNext()) {
RouteHeader route = (RouteHeader) routes.next();
SipURI uri = (SipURI) route.getAddress().getURI();
int port = uri.getPort();
port = (port == -1) ? 5060 : port;
String host = uri.getHost();
Log.debug("getNextHops", host);
String transport = uri.getTransportParam();
if (transport == null) {
transport = "udp";
}
Hop hop = new SipCommHop(host + ':' + port + '/' + transport);
hops.add(hop);
}
} else if (requestURI instanceof SipURI && ((SipURI) requestURI).getMAddrParam() != null) {
SipURI sipURI = ((SipURI) requestURI);
String maddr = sipURI.getMAddrParam();
String transport = sipURI.getTransportParam();
if (transport == null) {
transport = "udp";
}
int port = 5060;
Hop hop = new SipCommHop(maddr, port, transport);
hops.add(hop);
} else if (requestURI instanceof SipURI) {
SipURI sipURI = ((SipURI) requestURI);
int port = sipURI.getPort();
if (port == -1) {
port = 5060;
}
String host = sipURI.getHost();
String transport = sipURI.getTransportParam();
if (transport == null) {
transport = "UDP";
}
Hop hop = new SipCommHop(host + ":" + port + "/" + transport);
hops.add(hop);
} else {
throw new IllegalArgumentException("Malformed requestURI");
}
return (hops.size() == 0) ? null : hops.listIterator();
}
use of javax.sip.address.Hop in project XobotOS by xamarin.
the class SipProviderImpl method sendRequest.
/*
* (non-Javadoc)
*
* @see javax.sip.SipProvider#sendRequest(javax.sip.message.Request)
*/
public void sendRequest(Request request) throws SipException {
if (!sipStack.isAlive())
throw new SipException("Stack is stopped.");
// message.
if (((SIPRequest) request).getRequestLine() != null && request.getMethod().equals(Request.ACK)) {
Dialog dialog = sipStack.getDialog(((SIPRequest) request).getDialogId(false));
if (dialog != null && dialog.getState() != null) {
if (sipStack.isLoggingEnabled())
sipStack.getStackLogger().logWarning("Dialog exists -- you may want to use Dialog.sendAck() " + dialog.getState());
}
}
Hop hop = sipStack.getRouter((SIPRequest) request).getNextHop(request);
if (hop == null)
throw new SipException("could not determine next hop!");
SIPRequest sipRequest = (SIPRequest) request;
// Null request is used to send default proxy keepalive messages.
if ((!sipRequest.isNullRequest()) && sipRequest.getTopmostVia() == null)
throw new SipException("Invalid SipRequest -- no via header!");
try {
/*
* JvB: Via branch should already be OK, dont touch it here? Some
* apps forward statelessly, and then it's not set. So set only when
* not set already, dont overwrite CANCEL branch here..
*/
if (!sipRequest.isNullRequest()) {
Via via = sipRequest.getTopmostVia();
String branch = via.getBranch();
if (branch == null || branch.length() == 0) {
via.setBranch(sipRequest.getTransactionId());
}
}
MessageChannel messageChannel = null;
if (this.listeningPoints.containsKey(hop.getTransport().toUpperCase()))
messageChannel = sipStack.createRawMessageChannel(this.getListeningPoint(hop.getTransport()).getIPAddress(), this.getListeningPoint(hop.getTransport()).getPort(), hop);
if (messageChannel != null) {
messageChannel.sendMessage((SIPMessage) sipRequest, hop);
} else {
throw new SipException("Could not create a message channel for " + hop.toString());
}
} catch (IOException ex) {
if (sipStack.isLoggingEnabled()) {
sipStack.getStackLogger().logException(ex);
}
throw new SipException("IO Exception occured while Sending Request", ex);
} catch (ParseException ex1) {
InternalErrorHandler.handleException(ex1);
} finally {
if (sipStack.isLoggingEnabled())
sipStack.getStackLogger().logDebug("done sending " + request.getMethod() + " to hop " + hop);
}
}
use of javax.sip.address.Hop in project XobotOS by xamarin.
the class AuthenticationHelperImpl method handleChallenge.
/*
* (non-Javadoc)
*
* @see gov.nist.javax.sip.clientauthutils.AuthenticationHelper#handleChallenge(javax.sip.message.Response,
* javax.sip.ClientTransaction, javax.sip.SipProvider)
*/
public ClientTransaction handleChallenge(Response challenge, ClientTransaction challengedTransaction, SipProvider transactionCreator, int cacheTime) throws SipException, NullPointerException {
try {
if (sipStack.isLoggingEnabled()) {
sipStack.getStackLogger().logDebug("handleChallenge: " + challenge);
}
SIPRequest challengedRequest = ((SIPRequest) challengedTransaction.getRequest());
Request reoriginatedRequest = null;
/*
* If the challenged request is part of a Dialog and the
* Dialog is confirmed the re-originated request should be
* generated as an in-Dialog request.
*/
if (challengedRequest.getToTag() != null || challengedTransaction.getDialog() == null || challengedTransaction.getDialog().getState() != DialogState.CONFIRMED) {
reoriginatedRequest = (Request) challengedRequest.clone();
} else {
/*
* Re-originate the request by consulting the dialog. In particular
* the route set could change between the original request and the
* in-dialog challenge.
*/
reoriginatedRequest = challengedTransaction.getDialog().createRequest(challengedRequest.getMethod());
Iterator<String> headerNames = challengedRequest.getHeaderNames();
while (headerNames.hasNext()) {
String headerName = headerNames.next();
if (reoriginatedRequest.getHeader(headerName) != null) {
ListIterator<Header> iterator = reoriginatedRequest.getHeaders(headerName);
while (iterator.hasNext()) {
reoriginatedRequest.addHeader(iterator.next());
}
}
}
}
// remove the branch id so that we could use the request in a new
// transaction
removeBranchID(reoriginatedRequest);
if (challenge == null || reoriginatedRequest == null) {
throw new NullPointerException("A null argument was passed to handle challenge.");
}
ListIterator authHeaders = null;
if (challenge.getStatusCode() == Response.UNAUTHORIZED) {
authHeaders = challenge.getHeaders(WWWAuthenticateHeader.NAME);
} else if (challenge.getStatusCode() == Response.PROXY_AUTHENTICATION_REQUIRED) {
authHeaders = challenge.getHeaders(ProxyAuthenticateHeader.NAME);
} else {
throw new IllegalArgumentException("Unexpected status code ");
}
if (authHeaders == null) {
throw new IllegalArgumentException("Could not find WWWAuthenticate or ProxyAuthenticate headers");
}
// Remove all authorization headers from the request (we'll re-add them
// from cache)
reoriginatedRequest.removeHeader(AuthorizationHeader.NAME);
reoriginatedRequest.removeHeader(ProxyAuthorizationHeader.NAME);
// rfc 3261 says that the cseq header should be augmented for the new
// request. do it here so that the new dialog (created together with
// the new client transaction) takes it into account.
// Bug report - Fredrik Wickstrom
CSeqHeader cSeq = (CSeqHeader) reoriginatedRequest.getHeader((CSeqHeader.NAME));
try {
cSeq.setSeqNumber(cSeq.getSeqNumber() + 1l);
} catch (InvalidArgumentException ex) {
throw new SipException("Invalid CSeq -- could not increment : " + cSeq.getSeqNumber());
}
/* Resolve this to the next hop based on the previous lookup. If we are not using
* lose routing (RFC2543) then just attach hop as a maddr param.
*/
if (challengedRequest.getRouteHeaders() == null) {
Hop hop = ((SIPClientTransaction) challengedTransaction).getNextHop();
SipURI sipUri = (SipURI) reoriginatedRequest.getRequestURI();
// BEGIN android-added
if (!hop.getHost().equalsIgnoreCase(sipUri.getHost()) && !hop.equals(sipStack.getRouter(challengedRequest).getOutboundProxy()))
// END android-added
sipUri.setMAddrParam(hop.getHost());
if (hop.getPort() != -1)
sipUri.setPort(hop.getPort());
}
ClientTransaction retryTran = transactionCreator.getNewClientTransaction(reoriginatedRequest);
WWWAuthenticateHeader authHeader = null;
SipURI requestUri = (SipURI) challengedTransaction.getRequest().getRequestURI();
while (authHeaders.hasNext()) {
authHeader = (WWWAuthenticateHeader) authHeaders.next();
String realm = authHeader.getRealm();
AuthorizationHeader authorization = null;
String sipDomain;
if (this.accountManager instanceof SecureAccountManager) {
UserCredentialHash credHash = ((SecureAccountManager) this.accountManager).getCredentialHash(challengedTransaction, realm);
URI uri = reoriginatedRequest.getRequestURI();
sipDomain = credHash.getSipDomain();
authorization = this.getAuthorization(reoriginatedRequest.getMethod(), uri.toString(), (reoriginatedRequest.getContent() == null) ? "" : new String(reoriginatedRequest.getRawContent()), authHeader, credHash);
} else {
UserCredentials userCreds = ((AccountManager) this.accountManager).getCredentials(challengedTransaction, realm);
sipDomain = userCreds.getSipDomain();
if (userCreds == null)
throw new SipException("Cannot find user creds for the given user name and realm");
// we haven't yet authenticated this realm since we were
// started.
authorization = this.getAuthorization(reoriginatedRequest.getMethod(), reoriginatedRequest.getRequestURI().toString(), (reoriginatedRequest.getContent() == null) ? "" : new String(reoriginatedRequest.getRawContent()), authHeader, userCreds);
}
if (sipStack.isLoggingEnabled())
sipStack.getStackLogger().logDebug("Created authorization header: " + authorization.toString());
if (cacheTime != 0)
cachedCredentials.cacheAuthorizationHeader(sipDomain, authorization, cacheTime);
reoriginatedRequest.addHeader(authorization);
}
if (sipStack.isLoggingEnabled()) {
sipStack.getStackLogger().logDebug("Returning authorization transaction." + retryTran);
}
return retryTran;
} catch (SipException ex) {
throw ex;
} catch (Exception ex) {
sipStack.getStackLogger().logError("Unexpected exception ", ex);
throw new SipException("Unexpected exception ", ex);
}
}
Aggregations