package net.i2p.data.i2cp;
/*
* free (adj.): unencumbered; not under the control of others
* Written by jrandom in 2003 and released into the public domain
* with no warranty of any kind, either expressed or implied.
* It probably won't make your computer catch on fire, or eat
* your children, but it might. Use at your own risk.
*
*/
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Map;
import java.util.Properties;
import net.i2p.data.DataFormatException;
import net.i2p.data.DataHelper;
import net.i2p.util.OrderedProperties;
/**
* Request the other side to send us what they think the current time is.
* Only supported from client to router.
*
* Since 0.8.7, optionally include a version string.
* Since 0.9.11, optionally include options.
*/
public class GetDateMessage extends I2CPMessageImpl {
public final static int MESSAGE_TYPE = 32;
private String _version;
private Properties _options;
public GetDateMessage() {
super();
}
/**
* @param version the client's version String to be sent to the router; may be null
* @since 0.8.7
*/
public GetDateMessage(String version) {
super();
_version = version;
}
/**
* Defaults in GetDateMessage options are, in general, NOT honored.
* Defaults are not serialized out-of-JVM, and the router does not recognize defaults in-JVM.
* Client side must promote defaults to the primary map.
*
* @param version the client's version String to be sent to the router; may be null;
* must be non-null if options is non-null and non-empty.
* @param options Client options to be sent to the router; primarily for authentication; may be null;
* keys and values 255 bytes (not chars) max each
* @since 0.9.11
*/
public GetDateMessage(String version, Properties options) {
super();
if (version == null && options != null && !options.isEmpty())
throw new IllegalArgumentException();
_version = version;
_options = options;
}
/**
* @return may be null
* @since 0.8.7
*/
public String getVersion() {
return _version;
}
/**
* Retrieve any configuration options for the connection.
* Primarily for authentication.
*
* @return may be null
* @since 0.9.11
*/
public Properties getOptions() {
return _options;
}
@Override
protected void doReadMessage(InputStream in, int size) throws I2CPMessageException, IOException {
if (size > 0) {
try {
_version = DataHelper.readString(in);
if (size > 1 + _version.length()) // assume ascii
_options = DataHelper.readProperties(in);
} catch (DataFormatException dfe) {
throw new I2CPMessageException("Bad version string", dfe);
}
}
}
@Override
protected byte[] doWriteMessage() throws I2CPMessageException, IOException {
if (_version == null)
return new byte[0];
ByteArrayOutputStream os = new ByteArrayOutputStream(_options != null ? 128 : 16);
try {
DataHelper.writeString(os, _version);
if (_options != null && !_options.isEmpty())
DataHelper.writeProperties(os, _options, true); // UTF-8
} catch (DataFormatException dfe) {
throw new I2CPMessageException("Error writing out the message data", dfe);
}
return os.toByteArray();
}
public int getType() {
return MESSAGE_TYPE;
}
@Override
public String toString() {
StringBuilder buf = new StringBuilder();
buf.append("[GetDateMessage]");
buf.append("\n\tVersion: ").append(_version);
if (_options != null && !_options.isEmpty()) {
buf.append("\n\tOptions: #: ").append(_options.size());
Properties sorted = new OrderedProperties();
sorted.putAll(_options);
for (Map.Entry<Object, Object> e : sorted.entrySet()) {
String key = (String) e.getKey();
String val = (String) e.getValue();
buf.append("\n\t\t[").append(key).append("] = [").append(val).append("]");
}
}
return buf.toString();
}
}