package net.i2p.client;
import net.i2p.data.DateAndFlags;
/**
* Advanced options attached to a single outgoing I2CP message.
*
* Note that the packing of options into the 16-bit flags field is
* is subject to change. Therefore, for now, this is only recommended
* within RouterContext.
*
* Static methods are for OutboundClientMessageOneShotJob to decode the
* flags field on the router side.
*
* @since 0.9.2
*/
public class SendMessageOptions extends DateAndFlags {
/** all subject to change */
/**
* 1 means don't send, 0 means default
*/
private static final int LS_MASK = 0x0100;
/**
* Tags to send field:
* see below for possible values
*/
private static final int TAGS_SEND_MASK = 0x000f;
/**
* Possible values. Configured values will be rounded down.
* Note that ElGamalAESEngine enforces a max of 200 on receive.
*/
private static final int[] TAGS_SEND = {
0, 2, 4, 6, 8, 12, 16, 24,
32, 40, 51, 64, 80, 100, 125, 160
};
/**
* Tags threshold field:
* see below for possible values
*/
private static final int TAGS_REQD_MASK = 0x00f0;
/** Possible values. Configured values will be rounded down. */
private static final int[] TAGS_REQD = {
0, 2, 3, 6, 9, 14, 20, 27,
35, 45, 57, 72, 92, 117, 147, 192
};
/**
* Reliability bits 9-10
* @since 0.9.14
*/
public enum Reliability { DEFAULT, BEST_EFFORT, GUARANTEED, UNDEFINED }
private static final int BEST_EFFORT_MASK = 0x0200;
private static final int GUARANTEED_MASK = 0x0400;
private static final int RELIABILITY_MASK = BEST_EFFORT_MASK | GUARANTEED_MASK;
/** default true */
public void setSendLeaseSet(boolean yes) {
if (yes)
_flags &= ~LS_MASK;
else
_flags |= LS_MASK;
}
/** default true */
public boolean getSendLeaseSet() {
return getSendLeaseSet(_flags);
}
/** default true */
public static boolean getSendLeaseSet(int flags) {
return (flags & LS_MASK) == 0;
}
/**
* If we are low on tags, send this many.
* Power of 2 recommended - rounds down.
* default 0, meaning unset, use the SKM config (default 40)
* @param tags 0 or 2 to 128
*/
public void setTagsToSend(int tags) {
if (tags < 0)
throw new IllegalArgumentException();
_flags &= ~TAGS_SEND_MASK;
_flags |= valToCode(tags, TAGS_SEND);
}
/**
* If we are low on tags, send this many.
* @return default 0, meaning unset, use the SKM config (default 40)
*/
public int getTagsToSend() {
return getTagsToSend(_flags);
}
/**
* If we are low on tags, send this many.
* @return default 0, meaning unset, use the SKM config (default 40)
*/
public static int getTagsToSend(int flags) {
int exp = (flags & TAGS_SEND_MASK);
return codeToVal(exp, TAGS_SEND);
}
/**
* Low tag threshold. If less than this many, send more.
* Power of 2 recommended - rounds down.
* default 0, meaning unset, use the SKM config (default 30)
* @param tags 0 to 90
*/
public void setTagThreshold(int tags) {
if (tags < 0)
throw new IllegalArgumentException();
_flags &= ~TAGS_REQD_MASK;
_flags |= valToCode(tags, TAGS_REQD) << 4;
}
/**
* Low tag threshold. If less than this many, send more.
* @return default 0, meaning unset, use the SKM config (default 30)
*/
public int getTagThreshold() {
return getTagThreshold(_flags);
}
/**
* Low tag threshold. If less than this many, send more.
* @return default 0, meaning unset, use the SKM config (default 30)
*/
public static int getTagThreshold(int flags) {
int exp = (flags & TAGS_REQD_MASK) >> 4;
return codeToVal(exp, TAGS_REQD);
}
/** rounds down */
private static int valToCode(int val, int[] codes) {
// special case, round up so we don't turn it into default
if (val > 0 && val <= codes[1])
return 1;
for (int i = 1; i < codes.length; i++) {
if (val < codes[i])
return i - 1;
}
return codes.length - 1;
}
private static int codeToVal(int code, int[] codes) {
return codes[code];
}
/**
* default Reliability.DEFAULT
* @since 0.9.14
*/
public void setReliability(Reliability r) {
_flags &= ~RELIABILITY_MASK;
switch (r) {
case BEST_EFFORT:
_flags |= BEST_EFFORT_MASK;
break;
case GUARANTEED:
_flags |= GUARANTEED_MASK;
break;
case UNDEFINED:
_flags |= RELIABILITY_MASK;
break;
case DEFAULT:
default:
break;
}
}
/**
* default Reliability.DEFAULT
* @since 0.9.14
*/
public Reliability getReliability() {
return getReliability(_flags);
}
/**
* default Reliability.DEFAULT
* @since 0.9.14
*/
public static Reliability getReliability(int flags) {
switch (flags & RELIABILITY_MASK) {
case BEST_EFFORT_MASK:
return Reliability.BEST_EFFORT;
case GUARANTEED_MASK:
return Reliability.GUARANTEED;
default:
case RELIABILITY_MASK:
return Reliability.UNDEFINED;
case 0:
return Reliability.DEFAULT;
}
}
}