forked from I2P_Developers/i2p.i2p
SAM v3.3: Fixes after testing
- More error checking - Better error responses - Fix listen port and protocol for DATAGRAM and RAW - Fix adding sessions with duplicate dests to DB - Add more sessions in SAMStreamSink
This commit is contained in:
@ -42,6 +42,7 @@ class MasterSession extends SAMv3StreamSession implements SAMDatagramReceiver, S
|
||||
private final SAMv3DatagramServer dgs;
|
||||
private final Map<String, SAMMessageSess> sessions;
|
||||
private final StreamAcceptor streamAcceptor;
|
||||
private static final String[] INVALID_OPTS = { "PORT", "HOST", "FROM_PORT", "TO_PORT", "PROTOCOL" };
|
||||
|
||||
/**
|
||||
* Build a Session according to information
|
||||
@ -57,6 +58,11 @@ class MasterSession extends SAMv3StreamSession implements SAMDatagramReceiver, S
|
||||
public MasterSession(String nick, SAMv3DatagramServer dgServer, SAMv3Handler handler, Properties props)
|
||||
throws IOException, DataFormatException, SAMException {
|
||||
super(nick);
|
||||
for (int i = 0; i < INVALID_OPTS.length; i++) {
|
||||
String p = INVALID_OPTS[i];
|
||||
if (props.containsKey(p))
|
||||
throw new SAMException("MASTER session options may not contain " + p);
|
||||
}
|
||||
dgs = dgServer;
|
||||
sessions = new ConcurrentHashMap<String, SAMMessageSess>(4);
|
||||
this.handler = handler;
|
||||
@ -162,15 +168,13 @@ class MasterSession extends SAMv3StreamSession implements SAMDatagramReceiver, S
|
||||
|
||||
rec = new SessionRecord(getDestination().toBase64(), props, subhandler);
|
||||
try {
|
||||
if (!SAMv3Handler.sSessionsHash.put(nick, rec))
|
||||
return "Duplicate ID " + nick;
|
||||
SAMv3Handler.sSessionsHash.putDupDestOK(nick, rec);
|
||||
sessions.put(nick, sess);
|
||||
} catch (SessionsDB.ExistingIdException e) {
|
||||
return e.toString();
|
||||
} catch (SessionsDB.ExistingDestException e) {
|
||||
// fixme need new db method for dup dests
|
||||
return "Duplicate ID " + nick;
|
||||
}
|
||||
// listeners etc
|
||||
if (_log.shouldWarn())
|
||||
_log.warn("added " + style + " proto " + listenProtocol + " port " + listenPort);
|
||||
|
||||
sess.start();
|
||||
// all ok
|
||||
|
@ -67,11 +67,10 @@ abstract class SAMMessageSession implements SAMMessageSess {
|
||||
_log = I2PAppContext.getGlobalContext().logManager().getLog(getClass());
|
||||
if (_log.shouldLog(Log.DEBUG))
|
||||
_log.debug("Initializing SAM message-based session");
|
||||
|
||||
handler = new SAMMessageSessionHandler(destStream, props);
|
||||
session = handler.getSession();
|
||||
listenProtocol = I2PSession.PROTO_ANY;
|
||||
listenPort = I2PSession.PORT_ANY;
|
||||
handler = new SAMMessageSessionHandler(destStream, props);
|
||||
session = handler.getSession();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -89,11 +88,10 @@ abstract class SAMMessageSession implements SAMMessageSess {
|
||||
_log = I2PAppContext.getGlobalContext().logManager().getLog(getClass());
|
||||
if (_log.shouldLog(Log.DEBUG))
|
||||
_log.debug("Initializing SAM message-based session");
|
||||
|
||||
session = sess;
|
||||
handler = new SAMMessageSessionHandler(session);
|
||||
this.listenProtocol = listenProtocol;
|
||||
this.listenPort = listenPort;
|
||||
session = sess;
|
||||
handler = new SAMMessageSessionHandler(session);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -368,7 +368,7 @@ class SAMStreamSession implements SAMMessageSess {
|
||||
* @since 0.9.25 moved from subclass SAMv3StreamSession to implement SAMMessageSess
|
||||
*/
|
||||
public boolean sendBytes(String s, byte[] b, int pr, int fp, int tp) throws I2PSessionException {
|
||||
throw new I2PSessionException("Unsupported in stream or master session");
|
||||
throw new I2PSessionException("Unsupported in STREAM or MASTER session");
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -314,10 +314,13 @@ class SAMv3Handler extends SAMv1Handler
|
||||
} catch (IOException e) {
|
||||
if (_log.shouldLog(Log.DEBUG))
|
||||
_log.debug("Caught IOException in handler", e);
|
||||
writeString(SESSION_ERROR, e.getMessage());
|
||||
} catch (SAMException e) {
|
||||
_log.error("Unexpected exception for message [" + msg + ']', e);
|
||||
writeString(SESSION_ERROR, e.getMessage());
|
||||
} catch (RuntimeException e) {
|
||||
_log.error("Unexpected exception for message [" + msg + ']', e);
|
||||
writeString(SESSION_ERROR, e.getMessage());
|
||||
} finally {
|
||||
if (_log.shouldLog(Log.DEBUG))
|
||||
_log.debug("Stopping handler");
|
||||
@ -467,8 +470,6 @@ class SAMv3Handler extends SAMv1Handler
|
||||
// SAMStreamSession constructor.
|
||||
allProps.setProperty("i2p.streaming.enforceProtocol", "true");
|
||||
allProps.setProperty("i2cp.dontPublishLeaseSet", "false");
|
||||
allProps.setProperty("FROM_PORT", Integer.toString(I2PSession.PORT_UNSPECIFIED));
|
||||
allProps.setProperty("TO_PORT", Integer.toString(I2PSession.PORT_UNSPECIFIED));
|
||||
}
|
||||
|
||||
try {
|
||||
@ -530,9 +531,9 @@ class SAMv3Handler extends SAMv1Handler
|
||||
msg = msess.remove(nick, props);
|
||||
}
|
||||
if (msg == null)
|
||||
return writeString("SESSION STATUS RESULT=OK", opcode + ' ' + nick);
|
||||
return writeString("SESSION STATUS RESULT=OK ID=\"" + nick + '"', opcode + ' ' + nick);
|
||||
else
|
||||
return writeString(SESSION_ERROR, msg);
|
||||
return writeString(SESSION_ERROR + " ID=\"" + nick + '"', msg);
|
||||
} else {
|
||||
if (_log.shouldLog(Log.DEBUG))
|
||||
_log.debug("Unrecognized SESSION message opcode: \""
|
||||
@ -581,10 +582,9 @@ class SAMv3Handler extends SAMv1Handler
|
||||
|
||||
if ( session != null )
|
||||
{
|
||||
_log.error ( "STREAM message received, but this session is a master session" );
|
||||
|
||||
_log.error("v3 control socket cannot be used for STREAM");
|
||||
try {
|
||||
notifyStreamResult(true, "I2P_ERROR", "master session cannot be used for streams");
|
||||
notifyStreamResult(true, "I2P_ERROR", "v3 control socket cannot be used for STREAM");
|
||||
} catch (IOException e) {}
|
||||
return false;
|
||||
}
|
||||
|
@ -32,8 +32,7 @@ class SessionsDB {
|
||||
map = new HashMap<String, SessionRecord>() ;
|
||||
}
|
||||
|
||||
/** @return success */
|
||||
synchronized public boolean put( String nick, SessionRecord session )
|
||||
public synchronized void put(String nick, SessionRecord session)
|
||||
throws ExistingIdException, ExistingDestException
|
||||
{
|
||||
if ( map.containsKey(nick) ) {
|
||||
@ -44,14 +43,19 @@ class SessionsDB {
|
||||
throw new ExistingDestException();
|
||||
}
|
||||
}
|
||||
|
||||
if ( !map.containsKey(nick) ) {
|
||||
session.createThreadGroup("SAM session "+nick);
|
||||
map.put(nick, session) ;
|
||||
return true ;
|
||||
}
|
||||
else
|
||||
return false ;
|
||||
|
||||
/** @since 0.9.25 */
|
||||
public synchronized void putDupDestOK(String nick, SessionRecord session)
|
||||
throws ExistingIdException
|
||||
{
|
||||
if (map.containsKey(nick)) {
|
||||
throw new ExistingIdException();
|
||||
}
|
||||
session.createThreadGroup("SAM session "+nick);
|
||||
map.put(nick, session) ;
|
||||
}
|
||||
|
||||
/** @return true if removed */
|
||||
|
@ -137,6 +137,10 @@ public class SAMReader {
|
||||
if ( (eq > 0) && (eq < pair.length() - 1) ) {
|
||||
String name = pair.substring(0, eq);
|
||||
String val = pair.substring(eq+1);
|
||||
if (val.length() <= 0) {
|
||||
_log.error("Empty value for " + name);
|
||||
continue;
|
||||
}
|
||||
while ( (val.charAt(0) == '\"') && (val.length() > 0) )
|
||||
val = val.substring(1);
|
||||
while ( (val.length() > 0) && (val.charAt(val.length()-1) == '\"') )
|
||||
|
@ -702,8 +702,7 @@ public class SAMStreamSink {
|
||||
samOut.flush();
|
||||
if (_log.shouldLog(Log.DEBUG))
|
||||
_log.debug("SESSION " + command + " sent");
|
||||
if (mode == STREAM) {
|
||||
// why only waiting in stream mode?
|
||||
//if (mode == STREAM) {
|
||||
boolean ok;
|
||||
if (masterMode)
|
||||
ok = eventHandler.waitForSessionAddReply();
|
||||
@ -713,6 +712,22 @@ public class SAMStreamSink {
|
||||
throw new IOException("SESSION " + command + " failed");
|
||||
if (_log.shouldLog(Log.DEBUG))
|
||||
_log.debug("SESSION " + command + " reply found: " + ok);
|
||||
//}
|
||||
if (masterMode) {
|
||||
// do a bunch more
|
||||
req = "SESSION ADD STYLE=STREAM FROM_PORT=99 ID=stream99\n";
|
||||
samOut.write(req.getBytes("UTF-8"));
|
||||
req = "SESSION ADD STYLE=STREAM FROM_PORT=98 ID=stream98\n";
|
||||
samOut.write(req.getBytes("UTF-8"));
|
||||
req = "SESSION ADD STYLE=DATAGRAM PORT=9997 LISTEN_PORT=97 ID=dg97\n";
|
||||
samOut.write(req.getBytes("UTF-8"));
|
||||
req = "SESSION ADD STYLE=DATAGRAM PORT=9996 FROM_PORT=96 ID=dg96\n";
|
||||
samOut.write(req.getBytes("UTF-8"));
|
||||
req = "SESSION ADD STYLE=RAW PORT=9995 LISTEN_PORT=95 ID=raw95\n";
|
||||
samOut.write(req.getBytes("UTF-8"));
|
||||
req = "SESSION ADD STYLE=RAW PORT=9994 FROM_PORT=94 LISTEN_PROTOCOL=222 ID=raw94\n";
|
||||
samOut.write(req.getBytes("UTF-8"));
|
||||
samOut.flush();
|
||||
}
|
||||
req = "NAMING LOOKUP NAME=ME\n";
|
||||
samOut.write(req.getBytes("UTF-8"));
|
||||
|
Reference in New Issue
Block a user