SAM: Timeout for first command after HELLO

Better removal of command and opcode from properties
Send error message if no NAME key in LOOKUP
This commit is contained in:
zzz
2015-11-30 21:57:55 +00:00
parent 3c8cc16273
commit f778c23f0b
3 changed files with 32 additions and 23 deletions

View File

@ -62,12 +62,10 @@ class SAMHandlerFactory {
// Message format: HELLO VERSION [MIN=v1] [MAX=v2]
Properties props = SAMUtils.parseParams(line);
if (!"HELLO".equals(props.getProperty(SAMUtils.COMMAND)) ||
!"VERSION".equals(props.getProperty(SAMUtils.OPCODE))) {
if (!"HELLO".equals(props.remove(SAMUtils.COMMAND)) ||
!"VERSION".equals(props.remove(SAMUtils.OPCODE))) {
throw new SAMException("Must start with HELLO VERSION");
}
props.remove(SAMUtils.COMMAND);
props.remove(SAMUtils.OPCODE);
String minVer = props.getProperty("MIN");
if (minVer == null) {

View File

@ -15,6 +15,8 @@ import java.io.IOException;
import java.io.InterruptedIOException;
import java.net.ConnectException;
import java.net.NoRouteToHostException;
import java.net.Socket;
import java.net.SocketTimeoutException;
import java.nio.channels.SocketChannel;
import java.nio.ByteBuffer;
import java.util.Properties;
@ -48,6 +50,7 @@ class SAMv1Handler extends SAMHandler implements SAMRawReceiver, SAMDatagramRece
protected final long _id;
private static final AtomicLong __id = new AtomicLong();
private static final int FIRST_READ_TIMEOUT = 60*1000;
/**
* Create a new SAM version 1 handler. This constructor expects
@ -105,6 +108,7 @@ class SAMv1Handler extends SAMHandler implements SAMRawReceiver, SAMDatagramRece
_log.debug("SAM handling started");
try {
boolean gotFirstLine = false;
while (true) {
if (shouldStop()) {
if (_log.shouldLog(Log.DEBUG))
@ -122,33 +126,38 @@ class SAMv1Handler extends SAMHandler implements SAMRawReceiver, SAMDatagramRece
break;
}
buf.setLength(0);
// TODO set timeout first time
ReadLine.readLine(clientSocketChannel.socket(), buf, 0);
// first time, set a timeout
try {
Socket sock = clientSocketChannel.socket();
ReadLine.readLine(sock, buf, gotFirstLine ? 0 : FIRST_READ_TIMEOUT);
sock.setSoTimeout(0);
} catch (SocketTimeoutException ste) {
writeString("SESSION STATUS RESULT=I2P_ERROR MESSAGE=\"command timeout, bye\"\n");
break;
}
msg = buf.toString();
if (_log.shouldLog(Log.DEBUG)) {
_log.debug("New message received: [" + msg + ']');
}
props = SAMUtils.parseParams(msg);
domain = props.getProperty(SAMUtils.COMMAND);
domain = (String) props.remove(SAMUtils.COMMAND);
if (domain == null) {
if (_log.shouldLog(Log.DEBUG))
_log.debug("Ignoring newline");
continue;
}
opcode = props.getProperty(SAMUtils.OPCODE);
opcode = (String) props.remove(SAMUtils.OPCODE);
if (opcode == null) {
if (_log.shouldLog(Log.DEBUG))
_log.debug("Error in message format");
break;
}
props.remove(SAMUtils.COMMAND);
props.remove(SAMUtils.OPCODE);
if (_log.shouldLog(Log.DEBUG)) {
_log.debug("Parsing (domain: \"" + domain
+ "\"; opcode: \"" + opcode + "\")");
}
gotFirstLine = true;
if (domain.equals("STREAM")) {
canContinue = execStreamMessage(opcode, props);
} else if (domain.equals("DATAGRAM")) {
@ -360,16 +369,11 @@ class SAMv1Handler extends SAMHandler implements SAMRawReceiver, SAMDatagramRece
/* Parse and execute a NAMING message */
protected boolean execNamingMessage(String opcode, Properties props) {
if (opcode.equals("LOOKUP")) {
if (props.isEmpty()) {
_log.debug("No parameters specified in NAMING LOOKUP message");
return false;
}
String name = props.getProperty("NAME");
if (name == null) {
if (_log.shouldLog(Log.DEBUG))
_log.debug("Name to resolve not specified in NAMING message");
return false;
return writeString("NAMING REPLY RESULT=KEY_NOT_FOUND NAME=\"\" MESSAGE=\"Must specify NAME\"\n");
}
Destination dest = null ;

View File

@ -54,6 +54,7 @@ class SAMv3Handler extends SAMv1Handler
private volatile boolean streamForwardingSocket;
private final boolean sendPorts;
private long _lastPing;
private static final int FIRST_READ_TIMEOUT = 60*1000;
private static final int READ_TIMEOUT = 3*60*1000;
interface Session {
@ -272,6 +273,7 @@ class SAMv3Handler extends SAMv1Handler
InputStream in = socket.getInputStream();
StringBuilder buf = new StringBuilder(1024);
boolean gotFirstLine = false;
while (true) {
if (shouldStop()) {
if (_log.shouldLog(Log.DEBUG))
@ -329,23 +331,28 @@ class SAMv3Handler extends SAMv1Handler
}
} else {
buf.setLength(0);
// TODO first time, set a timeout
ReadLine.readLine(socket, buf, 0);
// first time, set a timeout
try {
ReadLine.readLine(socket, buf, gotFirstLine ? 0 : FIRST_READ_TIMEOUT);
socket.setSoTimeout(0);
} catch (SocketTimeoutException ste) {
writeString("SESSION STATUS RESULT=I2P_ERROR MESSAGE=\"command timeout, bye\"\n");
break;
}
line = buf.toString();
}
if (_log.shouldLog(Log.DEBUG))
_log.debug("New message received: [" + line + ']');
props = SAMUtils.parseParams(line);
domain = props.getProperty(SAMUtils.COMMAND);
domain = (String) props.remove(SAMUtils.COMMAND);
if (domain == null) {
if (_log.shouldLog(Log.DEBUG))
_log.debug("Ignoring newline");
continue;
}
opcode = props.getProperty(SAMUtils.OPCODE);
props.remove(SAMUtils.COMMAND);
props.remove(SAMUtils.OPCODE);
gotFirstLine = true;
opcode = (String) props.remove(SAMUtils.OPCODE);
if (_log.shouldLog(Log.DEBUG)) {
_log.debug("Parsing (domain: \"" + domain
+ "\"; opcode: \"" + opcode + "\")");