Respect port in regless SIP calls

fix-message-formatting 5187
Ingo Bauersachs 12 years ago
parent 5d5db5de79
commit 0d8d67ac0e

@ -2399,29 +2399,6 @@ public InetSocketAddress getIntendedDestination(Address destination)
*/
public InetSocketAddress getIntendedDestination(SipURI destination)
throws IllegalArgumentException
{
return getIntendedDestination(destination.getHost());
}
/**
* Returns the <tt>InetAddress</tt> that is most likely to be to be used
* as a next hop when contacting the specified <tt>destination</tt>. This is
* an utility method that is used whenever we have to choose one of our
* local addresses to put in the Via, Contact or (in the case of no
* registrar accounts) From headers. The method also takes into account
* the existence of an outbound proxy and in that case returns its address
* as the next hop.
*
* @param host the destination that we would contact.
*
* @return the <tt>InetSocketAddress</tt> that is most likely to be to be
* used as a next hop when contacting the specified <tt>destination</tt>.
*
* @throws IllegalArgumentException if <tt>destination</tt> is not a valid
* host/ip/fqdn.
*/
public InetSocketAddress getIntendedDestination(String host)
throws IllegalArgumentException
{
// Address
InetSocketAddress destinationInetAddress = null;
@ -2440,16 +2417,29 @@ public InetSocketAddress getIntendedDestination(String host)
}
else
{
String transport = destination.getTransportParam();
if (transport == null)
{
transport = getDefaultTransport();
}
int port = destination.getPort();
if (port == -1)
{
port = ListeningPoint.PORT_5060;
}
ProxyConnection tempConn = new AutoProxyConnection(
(SipAccountIDImpl)getAccountID(),
host,
getDefaultTransport());
destination.getHost(),
port,
transport);
try
{
if(tempConn.getNextAddress())
destinationInetAddress = tempConn.getAddress();
else
throw new IllegalArgumentException(host
throw new IllegalArgumentException(destination.getHost()
+ " could not be resolved to an internet address.");
}
catch (DnssecException e)
@ -2460,7 +2450,7 @@ public InetSocketAddress getIntendedDestination(String host)
if(logger.isDebugEnabled())
logger.debug("Returning address " + destinationInetAddress
+ " for destination " + host);
+ " for destination " + destination.getHost());
return destinationInetAddress;
}

@ -1,403 +1,407 @@
/*
* Jitsi, the OpenSource Java VoIP and Instant Messaging client.
*
* Distributable under LGPL license.
* See terms of license at gnu.org.
*/
package net.java.sip.communicator.impl.protocol.sip.net;
import static javax.sip.ListeningPoint.TCP;
import static javax.sip.ListeningPoint.TLS;
import static javax.sip.ListeningPoint.UDP;
import static net.java.sip.communicator.service.protocol.ProtocolProviderFactory.SERVER_ADDRESS;
import static net.java.sip.communicator.service.protocol.ProtocolProviderFactory.USER_ID;
import java.net.*;
import java.text.*;
import javax.sip.*;
import net.java.sip.communicator.impl.protocol.sip.*;
import net.java.sip.communicator.service.dns.*;
import net.java.sip.communicator.util.*;
/**
* Implementation of the autodetect proxy connection. Tries to resolve a SIP-
* server by querying DNS in this order: NAPTR-SRV-A; SRV-A; A.
*
* @author Ingo Bauersachs
*/
public class AutoProxyConnection
extends ProxyConnection
{
private enum State
{
New,
Naptr,
NaptrSrv,
NaptrSrvHosts,
NaptrSrvHostIPs,
Srv,
SrvHosts,
SrvHostIPs,
Hosts,
IP
}
/**
* Wrapper around {@link NetworkUtils} to support Unit Tests.
*/
protected static class LocalNetworkUtils
{
public InetAddress getInetAddress(String address)
throws UnknownHostException
{
return NetworkUtils.getInetAddress(address);
}
public String[][] getNAPTRRecords(String address)
throws ParseException, DnssecException
{
return NetworkUtils.getNAPTRRecords(address);
}
public SRVRecord[] getSRVRecords(String service, String proto,
String address) throws ParseException, DnssecException
{
return NetworkUtils.getSRVRecords(service, proto, address);
}
public InetSocketAddress[] getAandAAAARecords(String target, int port)
throws ParseException, DnssecException
{
return NetworkUtils.getAandAAAARecords(target, port);
}
public boolean isValidIPAddress(String address)
{
return NetworkUtils.isValidIPAddress(address);
}
public SRVRecord[] getSRVRecords(String domain)
throws ParseException, DnssecException
{
return NetworkUtils.getSRVRecords(domain);
}
}
private final static Logger logger
= Logger.getLogger(AutoProxyConnection.class);
private State state;
private String address;
private final String defaultTransport;
private LocalNetworkUtils nu = new LocalNetworkUtils();
private final static String[] transports = new String[]
{
ListeningPoint.TLS,
ListeningPoint.TCP,
ListeningPoint.UDP
};
private boolean hadSrvResults;
private String[][] naptrRecords;
private int naptrIndex;
private SRVRecord[] srvRecords;
private int srvRecordsIndex;
private int srvTransportIndex;
private InetSocketAddress socketAddresses[];
private int socketAddressIndex;
/**
* Creates a new instance of this class. Uses the server from the account.
*
* @param account the account of this SIP protocol instance
* @param defaultTransport the default transport to use when DNS does not
* provide a protocol through NAPTR or SRV
*/
public AutoProxyConnection( SipAccountIDImpl account,
String defaultTransport )
{
super(account);
this.defaultTransport = defaultTransport;
reset();
}
/**
* Creates a new instance of this class. Uses the supplied address instead
* of the server address from the account.
*
* @param account the account of this SIP protocol instance
* @param address the domain on which to perform autodetection
* @param defaultTransport the default transport to use when DNS does not
* provide a protocol through NAPTR or SRV
*/
public AutoProxyConnection( SipAccountIDImpl account, String address,
String defaultTransport )
{
super(account);
this.defaultTransport = defaultTransport;
reset();
this.address = address;
if (nu.isValidIPAddress(this.address))
{
this.state = State.IP;
}
}
/**
* Sets the NetworkUtils wrapper. Used for Unit-Testing.
* @param nu the the NetworkUtils wrapper.
*/
protected void setNetworkUtils(LocalNetworkUtils nu)
{
this.nu = nu;
}
/*
* (non-Javadoc)
*
* @see net.java.sip.communicator.impl.protocol.sip.net.ProxyConnection#
* getNextAddressFromDns()
*/
@Override
protected boolean getNextAddressFromDns()
throws DnssecException
{
try
{
return getNextAddressInternal();
}
catch(ParseException ex)
{
logger.error("Unable to get DNS data for <" + address
+ "> in state" + state, ex);
}
return false;
}
/**
* Gets the next address from DNS.
*
* @throws DnssecException When a DNSSEC failure occured during the lookup.
* @throws ParseException When a domain name (possibly returned from DNS
* itself) is invalid.
*/
private boolean getNextAddressInternal()
throws DnssecException, ParseException
{
switch(state)
{
case New:
state = State.Naptr;
return getNextAddressFromDns();
case IP:
if(socketAddressIndex == 0)
{
socketAddressIndex++;
try
{
socketAddress = new InetSocketAddress(
nu.getInetAddress(address),
ListeningPoint.TLS.equalsIgnoreCase(transport)
? ListeningPoint.PORT_5061
: ListeningPoint.PORT_5060
);
}
catch (UnknownHostException e)
{
//this is not supposed to happen
logger.error("invalid IP address: " + address, e);
return false;
}
transport = defaultTransport;
return true;
}
return false;
case Naptr:
naptrRecords = nu.getNAPTRRecords(address);
if(naptrRecords != null && naptrRecords.length > 0)
{
state = State.NaptrSrv;
naptrIndex = 0;
}
else
{
hadSrvResults = false;
state = State.Srv;
srvTransportIndex = 0;
}
return getNextAddressFromDns();
case NaptrSrv:
for(; naptrIndex < naptrRecords.length; naptrIndex++)
{
srvRecords = nu.getSRVRecords(
naptrRecords[naptrIndex][2]);
if(srvRecords != null && srvRecords.length > 0)
{
state = State.NaptrSrvHosts;
if(TLS.equalsIgnoreCase(naptrRecords[naptrIndex][1]))
transport = TLS;
else if(TCP.equalsIgnoreCase(naptrRecords[naptrIndex][1]))
transport = TCP;
else
transport = UDP;
srvRecordsIndex = 0;
if(getNextAddressFromDns())
{
naptrIndex++;
return true;
}
}
}
return false; //no more naptr's
case NaptrSrvHosts:
for(; srvRecordsIndex < srvRecords.length; srvRecordsIndex++)
{
socketAddresses = nu.getAandAAAARecords(
srvRecords[srvRecordsIndex].getTarget(),
srvRecords[srvRecordsIndex].getPort());
if(socketAddresses != null && socketAddresses.length > 0)
{
state = State.NaptrSrvHostIPs;
socketAddressIndex = 0;
if(getNextAddressFromDns())
{
srvRecordsIndex++;
return true;
}
}
}
state = State.NaptrSrv;
return getNextAddressFromDns(); //backtrack to next naptr
case NaptrSrvHostIPs:
if(socketAddressIndex >= socketAddresses.length)
{
state = State.NaptrSrvHosts;
return getNextAddressFromDns(); //backtrack to next srv
}
socketAddress = socketAddresses[socketAddressIndex];
socketAddressIndex++;
return true;
case Srv:
for(;srvTransportIndex < transports.length; srvTransportIndex++)
{
srvRecords = nu.getSRVRecords(
(TLS.equals(transports[srvTransportIndex])
? "sips"
: "sip"),
(UDP.equalsIgnoreCase(transports[srvTransportIndex])
? UDP
: TCP),
address);
if(srvRecords != null && srvRecords.length > 0)
{
hadSrvResults = true;
state = State.SrvHosts;
srvRecordsIndex = 0;
transport = transports[srvTransportIndex];
if(getNextAddressFromDns())
{
srvTransportIndex++;
return true;
}
}
}
if(!hadSrvResults)
{
state = State.Hosts;
socketAddressIndex = 0;
return getNextAddressFromDns();
}
return false;
case SrvHosts:
if(srvRecordsIndex >= srvRecords.length)
{
state = State.Srv;
return getNextAddressFromDns(); //backtrack to next srv record
}
for(; srvRecordsIndex < srvRecords.length; srvRecordsIndex++)
{
socketAddresses = nu.getAandAAAARecords(
srvRecords[srvRecordsIndex].getTarget(),
srvRecords[srvRecordsIndex].getPort());
if(socketAddresses != null && socketAddresses.length > 0)
{
state = State.SrvHostIPs;
socketAddressIndex = 0;
if(getNextAddressFromDns())
{
srvRecordsIndex++;
return true;
}
}
}
return false;
case SrvHostIPs:
if(socketAddressIndex >= socketAddresses.length)
{
state = State.SrvHosts;
return getNextAddressFromDns();
}
socketAddress = socketAddresses[socketAddressIndex];
socketAddressIndex++;
return true;
case Hosts:
transport = defaultTransport;
if(socketAddresses == null)
{
socketAddresses = nu.getAandAAAARecords(
address,
ListeningPoint.PORT_5060);
}
if(socketAddresses != null && socketAddresses.length > 0
&& socketAddressIndex < socketAddresses.length)
{
socketAddress = socketAddresses[socketAddressIndex++];
return true;
}
return false;
}
return false;
}
/*
* (non-Javadoc)
*
* @see
* net.java.sip.communicator.impl.protocol.sip.net.ProxyConnection#reset()
*/
@Override
public void reset()
{
super.reset();
state = State.New;
//determine the hostname of the proxy for autodetection:
//1) server part of the user ID
//2) name of the registrar when the user ID contains no domain
String userID = account.getAccountPropertyString(USER_ID);
int domainIx = userID.indexOf("@");
if(domainIx > 0)
{
address = userID.substring(domainIx + 1);
}
else
{
address = account.getAccountPropertyString(SERVER_ADDRESS);
if(address == null || address.trim().length() == 0)
{
//registrarless account
return;
}
}
if(nu.isValidIPAddress(address))
{
state = State.IP;
socketAddressIndex = 0;
}
}
}
/*
* Jitsi, the OpenSource Java VoIP and Instant Messaging client.
*
* Distributable under LGPL license.
* See terms of license at gnu.org.
*/
package net.java.sip.communicator.impl.protocol.sip.net;
import static javax.sip.ListeningPoint.TCP;
import static javax.sip.ListeningPoint.TLS;
import static javax.sip.ListeningPoint.UDP;
import static net.java.sip.communicator.service.protocol.ProtocolProviderFactory.SERVER_ADDRESS;
import static net.java.sip.communicator.service.protocol.ProtocolProviderFactory.USER_ID;
import java.net.*;
import java.text.*;
import javax.sip.*;
import net.java.sip.communicator.impl.protocol.sip.*;
import net.java.sip.communicator.service.dns.*;
import net.java.sip.communicator.util.*;
/**
* Implementation of the autodetect proxy connection. Tries to resolve a SIP-
* server by querying DNS in this order: NAPTR-SRV-A; SRV-A; A.
*
* @author Ingo Bauersachs
*/
public class AutoProxyConnection
extends ProxyConnection
{
private enum State
{
New,
Naptr,
NaptrSrv,
NaptrSrvHosts,
NaptrSrvHostIPs,
Srv,
SrvHosts,
SrvHostIPs,
Hosts,
IP
}
/**
* Wrapper around {@link NetworkUtils} to support Unit Tests.
*/
protected static class LocalNetworkUtils
{
public InetAddress getInetAddress(String address)
throws UnknownHostException
{
return NetworkUtils.getInetAddress(address);
}
public String[][] getNAPTRRecords(String address)
throws ParseException, DnssecException
{
return NetworkUtils.getNAPTRRecords(address);
}
public SRVRecord[] getSRVRecords(String service, String proto,
String address) throws ParseException, DnssecException
{
return NetworkUtils.getSRVRecords(service, proto, address);
}
public InetSocketAddress[] getAandAAAARecords(String target, int port)
throws ParseException, DnssecException
{
return NetworkUtils.getAandAAAARecords(target, port);
}
public boolean isValidIPAddress(String address)
{
return NetworkUtils.isValidIPAddress(address);
}
public SRVRecord[] getSRVRecords(String domain)
throws ParseException, DnssecException
{
return NetworkUtils.getSRVRecords(domain);
}
}
private final static Logger logger
= Logger.getLogger(AutoProxyConnection.class);
private State state;
private String address;
private int port;
private final String defaultTransport;
private LocalNetworkUtils nu = new LocalNetworkUtils();
private final static String[] transports = new String[]
{
ListeningPoint.TLS,
ListeningPoint.TCP,
ListeningPoint.UDP
};
private boolean hadSrvResults;
private String[][] naptrRecords;
private int naptrIndex;
private SRVRecord[] srvRecords;
private int srvRecordsIndex;
private int srvTransportIndex;
private InetSocketAddress socketAddresses[];
private int socketAddressIndex;
/**
* Creates a new instance of this class. Uses the server from the account.
*
* @param account the account of this SIP protocol instance
* @param defaultTransport the default transport to use when DNS does not
* provide a protocol through NAPTR or SRV
*/
public AutoProxyConnection( SipAccountIDImpl account,
String defaultTransport )
{
super(account);
port = ListeningPoint.PORT_5060;
this.defaultTransport = defaultTransport;
reset();
}
/**
* Creates a new instance of this class. Uses the supplied address instead
* of the server address from the account.
*
* @param account the account of this SIP protocol instance
* @param address the domain on which to perform autodetection
* @param port the destination socket port
* @param defaultTransport the default transport to use when DNS does not
* provide a protocol through NAPTR or SRV
*/
public AutoProxyConnection( SipAccountIDImpl account, String address,
int port, String defaultTransport )
{
super(account);
this.defaultTransport = defaultTransport;
this.port = port;
reset();
this.address = address;
if (nu.isValidIPAddress(this.address))
{
this.state = State.IP;
}
}
/**
* Sets the NetworkUtils wrapper. Used for Unit-Testing.
* @param nu the the NetworkUtils wrapper.
*/
protected void setNetworkUtils(LocalNetworkUtils nu)
{
this.nu = nu;
}
/*
* (non-Javadoc)
*
* @see net.java.sip.communicator.impl.protocol.sip.net.ProxyConnection#
* getNextAddressFromDns()
*/
@Override
protected boolean getNextAddressFromDns()
throws DnssecException
{
try
{
return getNextAddressInternal();
}
catch(ParseException ex)
{
logger.error("Unable to get DNS data for <" + address
+ "> in state" + state, ex);
}
return false;
}
/**
* Gets the next address from DNS.
*
* @throws DnssecException When a DNSSEC failure occured during the lookup.
* @throws ParseException When a domain name (possibly returned from DNS
* itself) is invalid.
*/
private boolean getNextAddressInternal()
throws DnssecException, ParseException
{
switch(state)
{
case New:
state = State.Naptr;
return getNextAddressFromDns();
case IP:
if(socketAddressIndex == 0)
{
socketAddressIndex++;
try
{
socketAddress = new InetSocketAddress(
nu.getInetAddress(address),
ListeningPoint.TLS.equalsIgnoreCase(transport)
? ListeningPoint.PORT_5061
: ListeningPoint.PORT_5060
);
}
catch (UnknownHostException e)
{
//this is not supposed to happen
logger.error("invalid IP address: " + address, e);
return false;
}
transport = defaultTransport;
return true;
}
return false;
case Naptr:
naptrRecords = nu.getNAPTRRecords(address);
if(naptrRecords != null && naptrRecords.length > 0)
{
state = State.NaptrSrv;
naptrIndex = 0;
}
else
{
hadSrvResults = false;
state = State.Srv;
srvTransportIndex = 0;
}
return getNextAddressFromDns();
case NaptrSrv:
for(; naptrIndex < naptrRecords.length; naptrIndex++)
{
srvRecords = nu.getSRVRecords(
naptrRecords[naptrIndex][2]);
if(srvRecords != null && srvRecords.length > 0)
{
state = State.NaptrSrvHosts;
if(TLS.equalsIgnoreCase(naptrRecords[naptrIndex][1]))
transport = TLS;
else if(TCP.equalsIgnoreCase(naptrRecords[naptrIndex][1]))
transport = TCP;
else
transport = UDP;
srvRecordsIndex = 0;
if(getNextAddressFromDns())
{
naptrIndex++;
return true;
}
}
}
return false; //no more naptr's
case NaptrSrvHosts:
for(; srvRecordsIndex < srvRecords.length; srvRecordsIndex++)
{
socketAddresses = nu.getAandAAAARecords(
srvRecords[srvRecordsIndex].getTarget(),
srvRecords[srvRecordsIndex].getPort());
if(socketAddresses != null && socketAddresses.length > 0)
{
state = State.NaptrSrvHostIPs;
socketAddressIndex = 0;
if(getNextAddressFromDns())
{
srvRecordsIndex++;
return true;
}
}
}
state = State.NaptrSrv;
return getNextAddressFromDns(); //backtrack to next naptr
case NaptrSrvHostIPs:
if(socketAddressIndex >= socketAddresses.length)
{
state = State.NaptrSrvHosts;
return getNextAddressFromDns(); //backtrack to next srv
}
socketAddress = socketAddresses[socketAddressIndex];
socketAddressIndex++;
return true;
case Srv:
for(;srvTransportIndex < transports.length; srvTransportIndex++)
{
srvRecords = nu.getSRVRecords(
(TLS.equals(transports[srvTransportIndex])
? "sips"
: "sip"),
(UDP.equalsIgnoreCase(transports[srvTransportIndex])
? UDP
: TCP),
address);
if(srvRecords != null && srvRecords.length > 0)
{
hadSrvResults = true;
state = State.SrvHosts;
srvRecordsIndex = 0;
transport = transports[srvTransportIndex];
if(getNextAddressFromDns())
{
srvTransportIndex++;
return true;
}
}
}
if(!hadSrvResults)
{
state = State.Hosts;
socketAddressIndex = 0;
return getNextAddressFromDns();
}
return false;
case SrvHosts:
if(srvRecordsIndex >= srvRecords.length)
{
state = State.Srv;
return getNextAddressFromDns(); //backtrack to next srv record
}
for(; srvRecordsIndex < srvRecords.length; srvRecordsIndex++)
{
socketAddresses = nu.getAandAAAARecords(
srvRecords[srvRecordsIndex].getTarget(),
srvRecords[srvRecordsIndex].getPort());
if(socketAddresses != null && socketAddresses.length > 0)
{
state = State.SrvHostIPs;
socketAddressIndex = 0;
if(getNextAddressFromDns())
{
srvRecordsIndex++;
return true;
}
}
}
return false;
case SrvHostIPs:
if(socketAddressIndex >= socketAddresses.length)
{
state = State.SrvHosts;
return getNextAddressFromDns();
}
socketAddress = socketAddresses[socketAddressIndex];
socketAddressIndex++;
return true;
case Hosts:
transport = defaultTransport;
if(socketAddresses == null)
{
socketAddresses = nu.getAandAAAARecords(
address,
port);
}
if(socketAddresses != null && socketAddresses.length > 0
&& socketAddressIndex < socketAddresses.length)
{
socketAddress = socketAddresses[socketAddressIndex++];
return true;
}
return false;
}
return false;
}
/*
* (non-Javadoc)
*
* @see
* net.java.sip.communicator.impl.protocol.sip.net.ProxyConnection#reset()
*/
@Override
public void reset()
{
super.reset();
state = State.New;
//determine the hostname of the proxy for autodetection:
//1) server part of the user ID
//2) name of the registrar when the user ID contains no domain
String userID = account.getAccountPropertyString(USER_ID);
int domainIx = userID.indexOf("@");
if(domainIx > 0)
{
address = userID.substring(domainIx + 1);
}
else
{
address = account.getAccountPropertyString(SERVER_ADDRESS);
if(address == null || address.trim().length() == 0)
{
//registrarless account
return;
}
}
if(nu.isValidIPAddress(address))
{
state = State.IP;
socketAddressIndex = 0;
}
}
}

Loading…
Cancel
Save