Version handling (ticket #1318)
   - MAX param now optional
   - 1-digit versions now accepted for MIN and MAX
   - Use VersionComparator for version tests
   - Don't require a minor version of 0
   - Fix empty properties check
   - Overrides
   - Prep for version 3.1
  Throw exception on null option key (ticket #1325)
This commit is contained in:
zzz
2014-06-27 20:36:34 +00:00
parent d8c8586ccf
commit 0fc3029aaa
5 changed files with 51 additions and 40 deletions

View File

@ -17,12 +17,14 @@ import java.util.StringTokenizer;
import net.i2p.data.DataHelper;
import net.i2p.util.Log;
import net.i2p.util.VersionComparator;
/**
* SAM handler factory class.
*/
class SAMHandlerFactory {
private static final String VERSION = "3.0";
/**
* Return the right SAM handler depending on the protocol version
@ -66,9 +68,8 @@ class SAMHandlerFactory {
}
}
Properties props;
props = SAMUtils.parseParams(tok);
if (props == null) {
Properties props = SAMUtils.parseParams(tok);
if (props.isEmpty()) {
throw new SAMException("No parameters in HELLO VERSION message");
}
@ -79,7 +80,9 @@ class SAMHandlerFactory {
String maxVer = props.getProperty("MAX");
if (maxVer == null) {
throw new SAMException("Missing MAX parameter in HELLO VERSION message");
//throw new SAMException("Missing MAX parameter in HELLO VERSION message");
// MAX optional as of 0.9.14
maxVer = "99.99";
}
String ver = chooseBestVersion(minVer, maxVer);
@ -119,30 +122,28 @@ class SAMHandlerFactory {
return handler;
}
/* Return the best version we can use, or null on failure */
/*
* @return "x.y" the best version we can use, or null on failure
*/
private static String chooseBestVersion(String minVer, String maxVer) {
int minMajor = getMajor(minVer), minMinor = getMinor(minVer);
int maxMajor = getMajor(maxVer), maxMinor = getMinor(maxVer);
// Consistency checks
if ((minMajor == -1) || (minMinor == -1)
|| (maxMajor == -1) || (maxMinor == -1)) {
return null;
// in VersionComparator, "3" < "3.0" so
// use comparisons carefully
if (VersionComparator.comp("3.0", minVer) >= 0) {
// Documentation said:
// In order to force protocol version 3.0, the values of $min and $max
// must be "3.0".
int maxcomp = VersionComparator.comp("3", maxVer);
if (maxcomp == 0 || maxVer.equals("3.0"))
return "3.0"; // spoof version
if (maxcomp < 0)
return VERSION;
}
if ((minMinor >= 10) || (maxMinor >= 10)) return null ;
float fminVer = minMajor + (float) minMinor / 10 ;
float fmaxVer = maxMajor + (float) maxMinor / 10 ;
if ( ( fminVer <= 3.0 ) && ( fmaxVer >= 3.0 ) ) return "3.0" ;
if ( ( fminVer <= 2.0 ) && ( fmaxVer >= 2.0 ) ) return "2.0" ;
if ( ( fminVer <= 1.0 ) && ( fmaxVer >= 1.0 ) ) return "1.0" ;
if (VersionComparator.comp("2.0", minVer) >= 0 &&
VersionComparator.comp("2", maxVer) <= 0)
return "2.0";
if (VersionComparator.comp("1.0", minVer) >= 0 &&
VersionComparator.comp("1", maxVer) <= 0)
return "1.0";
return null;
}

View File

@ -159,26 +159,34 @@ class SAMUtils {
* @param tok A StringTokenizer pointing to the SAM parameters
*
* @throws SAMException if the data was formatted incorrectly
* @return Properties with the parsed SAM params
* @return Properties with the parsed SAM params, never null
*/
public static Properties parseParams(StringTokenizer tok) throws SAMException {
int pos, ntoks = tok.countTokens();
String token, param;
int ntoks = tok.countTokens();
Properties props = new Properties();
StringBuilder value = new StringBuilder();
for (int i = 0; i < ntoks; ++i) {
token = tok.nextToken();
String token = tok.nextToken();
pos = token.indexOf("=");
if (pos == -1) {
int pos = token.indexOf("=");
if (pos <= 0) {
//_log.debug("Error in params format");
if (pos == 0) {
throw new SAMException("No param specified [" + token + "]");
} else {
throw new SAMException("Bad formatting for param [" + token + "]");
}
param = token.substring(0, pos);
}
String param = token.substring(0, pos);
value.append(token.substring(pos+1));
if (value.length() == 0)
throw new SAMException("Empty value for param " + param);
// FIXME: The following code does not take into account that there
// may have been multiple subsequent space chars in the input that
// StringTokenizer treates as one.
if (value.charAt(0) == '"') {
while ( (i < ntoks) && (value.lastIndexOf("\"") <= 0) ) {
value.append(' ').append(tok.nextToken());

View File

@ -86,7 +86,7 @@ class SAMv1Handler extends SAMHandler implements SAMRawReceiver, SAMDatagramRece
}
public boolean verifVersion() {
return ( verMajor == 1 && verMinor == 0 ) ;
return (verMajor == 1);
}
public void handle() {

View File

@ -55,9 +55,10 @@ class SAMv2Handler extends SAMv1Handler implements SAMRawReceiver, SAMDatagramRe
super ( s, verMajor, verMinor, i2cpProps );
}
@Override
public boolean verifVersion()
{
return (verMajor == 2 && verMinor == 0) ;
return (verMajor == 2);
}
SAMStreamSession newSAMStreamSession(String destKeystream, String direction, Properties props )

View File

@ -88,9 +88,10 @@ class SAMv3Handler extends SAMv1Handler
_log.debug("SAM version 3 handler instantiated");
}
@Override
public boolean verifVersion()
{
return (verMajor == 3 && verMinor == 0) ;
return (verMajor == 3);
}
public static class DatagramServer {