UdpEndpointI.java
// Copyright (c) ZeroC, Inc.
package com.zeroc.Ice;
import com.zeroc.Ice.SSL.SSLEngineFactory;
import java.net.InetSocketAddress;
import java.util.ArrayList;
final class UdpEndpointI extends IPEndpointI {
public UdpEndpointI(
ProtocolInstance instance,
String host,
int port,
InetSocketAddress sourceAddr,
String mcastInterface,
int mttl,
String connectionId,
boolean compress) {
super(instance, host, port, sourceAddr, connectionId);
_mcastInterface = mcastInterface;
_mcastTtl = mttl;
_compress = compress;
}
public UdpEndpointI(ProtocolInstance instance) {
super(instance);
_compress = false;
}
public UdpEndpointI(ProtocolInstance instance, InputStream s) {
super(instance, s);
if (s.getEncoding().equals(Util.Encoding_1_0)) {
s.readByte();
s.readByte();
s.readByte();
s.readByte();
}
_compress = s.readBool();
}
//
// Return the endpoint information.
//
@Override
public EndpointInfo getInfo() {
return new UDPEndpointInfo(
_compress,
_host,
_port,
_sourceAddr == null ? "" : _sourceAddr.getAddress().getHostAddress(),
_mcastInterface,
_mcastTtl);
}
//
// Return the timeout for the endpoint in milliseconds. 0 means
// non-blocking, -1 means no timeout.
//
@Override
public int timeout() {
return -1;
}
//
// Return a new endpoint with a different timeout value, provided
// that timeouts are supported by the endpoint. Otherwise the same
// endpoint is returned.
//
@Override
public EndpointI timeout(int timeout) {
return this;
}
//
// Return true if the endpoints support bzip2 compress, or false
// otherwise.
//
@Override
public boolean compress() {
return _compress;
}
//
// Return a new endpoint with a different compression value,
// provided that compression is supported by the
// endpoint. Otherwise the same endpoint is returned.
//
@Override
public EndpointI compress(boolean compress) {
if (compress == _compress) {
return this;
} else {
return new UdpEndpointI(
_instance,
_host,
_port,
_sourceAddr,
_mcastInterface,
_mcastTtl,
_connectionId,
compress);
}
}
//
// Return true if the endpoint is datagram-based.
//
@Override
public boolean datagram() {
return true;
}
//
// Return a server side transceiver for this endpoint, or null if a
// transceiver can only be created by an acceptor.
//
@Override
public Transceiver transceiver() {
InetSocketAddress addr =
Network.getAddressForServer(
_host, _port, _instance.protocolSupport(), _instance.preferIPv6());
if (Util.isAndroid() && addr.getAddress().isMulticastAddress()) {
return new UdpMulticastServerTransceiver(this, _instance, addr, _mcastInterface);
} else {
return new UdpTransceiver(this, _instance, addr, _mcastInterface);
}
}
//
// Return an acceptor for this endpoint, or null if no acceptor is available.
//
@Override
public Acceptor acceptor(String adapterName, SSLEngineFactory factory) {
assert (factory == null);
return null;
}
public UdpEndpointI endpoint(UdpTransceiver transceiver) {
int port = transceiver.effectivePort();
if (port == _port) {
return this;
} else {
return new UdpEndpointI(
_instance,
_host,
port,
_sourceAddr,
_mcastInterface,
_mcastTtl,
_connectionId,
_compress);
}
}
public UdpEndpointI endpoint(UdpMulticastServerTransceiver transceiver) {
int port = transceiver.effectivePort();
if (port == _port) {
return this;
} else {
return new UdpEndpointI(
_instance,
_host,
port,
_sourceAddr,
_mcastInterface,
_mcastTtl,
_connectionId,
_compress);
}
}
@Override
public void initWithOptions(ArrayList<String> args, boolean oaEndpoint) {
super.initWithOptions(args, oaEndpoint);
if ("*".equals(_mcastInterface)) {
if (oaEndpoint) {
_mcastInterface = "";
} else {
throw new ParseException(
"'--interface *' not valid for proxy endpoint '" + toString() + "'");
}
}
}
//
// Convert the endpoint to its string form
//
@Override
public String options() {
//
// WARNING: Certain features, such as proxy validation in Glacier2,
// depend on the format of proxy strings. Changes to toString() and
// methods called to generate parts of the reference string could break
// these features. Please review for all features that depend on the
// format of proxyToString() before changing this and related code.
//
String s = super.options();
if (!_mcastInterface.isEmpty()) {
s += " --interface ";
boolean addQuote = _mcastInterface.indexOf(':') != -1;
if (addQuote) {
s += "\"";
}
s += _mcastInterface;
if (addQuote) {
s += "\"";
}
}
if (_mcastTtl != -1) {
s += " --ttl " + _mcastTtl;
}
if (_compress) {
s += " -z";
}
return s;
}
@Override
public int compareTo(EndpointI obj) {
if (!(obj instanceof UdpEndpointI)) {
return type() < obj.type() ? -1 : 1;
}
UdpEndpointI p = (UdpEndpointI) obj;
if (this == p) {
return 0;
}
if (!_compress && p._compress) {
return -1;
} else if (!p._compress && _compress) {
return 1;
}
if (_mcastTtl < p._mcastTtl) {
return -1;
} else if (p._mcastTtl < _mcastTtl) {
return 1;
}
int rc = _mcastInterface.compareTo(p._mcastInterface);
if (rc != 0) {
return rc;
}
return super.compareTo(obj);
}
//
// Marshal the endpoint
//
@Override
public void streamWriteImpl(OutputStream s) {
super.streamWriteImpl(s);
if (s.getEncoding().equals(Util.Encoding_1_0)) {
Util.Protocol_1_0.ice_writeMembers(s);
Util.Encoding_1_0.ice_writeMembers(s);
}
s.writeBool(_compress);
}
@Override
public int hashCode() {
int h = super.hashCode();
h = HashUtil.hashAdd(h, _mcastInterface);
h = HashUtil.hashAdd(h, _mcastTtl);
h = HashUtil.hashAdd(h, _compress);
return h;
}
@Override
public EndpointI toPublishedEndpoint(String publishedHost) {
return new UdpEndpointI(
_instance,
publishedHost.isEmpty() ? _host : publishedHost,
_port,
null,
"",
-1,
"",
_compress);
}
@Override
protected boolean checkOption(String option, String argument, String endpoint) {
if (super.checkOption(option, argument, endpoint)) {
return true;
}
if ("-z".equals(option)) {
if (argument != null) {
throw new ParseException(
"unexpected argument '"
+ argument
+ "' provided for -z option in '"
+ endpoint
+ "'");
}
_compress = true;
} else if ("-v".equals(option) || "-e".equals(option)) {
if (argument == null) {
throw new ParseException(
"no argument provided for "
+ option
+ " option in endpoint '"
+ endpoint
+ "'");
}
try {
EncodingVersion v = Util.stringToEncodingVersion(argument);
if (v.major != 1 || v.minor != 0) {
_instance.logger().warning("deprecated udp endpoint option: " + option);
}
} catch (ParseException ex) {
throw new ParseException(
"invalid version '" + argument + "' in endpoint '" + endpoint + "'", ex);
}
} else if ("--ttl".equals(option)) {
if (argument == null) {
throw new ParseException(
"no argument provided for --ttl option in endpoint '" + endpoint + "'");
}
try {
_mcastTtl = Integer.parseInt(argument);
} catch (NumberFormatException ex) {
throw new ParseException(
"invalid TTL value '" + argument + "' in endpoint '" + endpoint + "'", ex);
}
if (_mcastTtl < 0) {
throw new ParseException(
"TTL value '" + argument + "' out of range in endpoint '" + endpoint + "'");
}
} else if ("--interface".equals(option)) {
if (argument == null) {
throw new ParseException(
"no argument provided for --interface option in endpoint '"
+ endpoint
+ "'");
}
_mcastInterface = argument;
} else {
return false;
}
return true;
}
@Override
protected Connector createConnector(InetSocketAddress addr, NetworkProxy proxy) {
return new UdpConnector(
_instance, addr, _sourceAddr, _mcastInterface, _mcastTtl, _connectionId);
}
@Override
protected IPEndpointI createEndpoint(String host, int port, String connectionId) {
return new UdpEndpointI(
_instance,
host,
port,
_sourceAddr,
_mcastInterface,
_mcastTtl,
connectionId,
_compress);
}
private String _mcastInterface = "";
private int _mcastTtl = -1;
private boolean _compress;
}