forked from I2P_Developers/i2p.i2p
SAM v3.3: Fixes after testing
- Set Master properties in handler, not in session, so they take - Create subhandlers for the subsessions - Create socket manager with preferred createDisconectedManager() so we get exceptions - Fix check for master session - Enhance error messages - Add basic master session test for SAMStreamSend - Add check for DESTINATION in SESSION ADD - Don't return DESTINATION in an I2P_ERROR response Next to do: master support in SAMStreamSink
This commit is contained in:
@@ -56,10 +56,6 @@ class MasterSession extends SAMv3StreamSession implements SAMDatagramReceiver, S
|
|||||||
public MasterSession(String nick, SAMv3DatagramServer dgServer, SAMv3Handler handler, Properties props)
|
public MasterSession(String nick, SAMv3DatagramServer dgServer, SAMv3Handler handler, Properties props)
|
||||||
throws IOException, DataFormatException, SAMException {
|
throws IOException, DataFormatException, SAMException {
|
||||||
super(nick);
|
super(nick);
|
||||||
props.setProperty("net.i2p.streaming.enforceProtocol", "true");
|
|
||||||
props.setProperty("i2cp.dontPublishLeaseSet", "false");
|
|
||||||
props.setProperty("FROM_PORT", Integer.toString(I2PSession.PORT_UNSPECIFIED));
|
|
||||||
props.setProperty("TO_PORT", Integer.toString(I2PSession.PORT_UNSPECIFIED));
|
|
||||||
dgs = dgServer;
|
dgs = dgServer;
|
||||||
sessions = new ConcurrentHashMap<String, SAMMessageSess>(4);
|
sessions = new ConcurrentHashMap<String, SAMMessageSess>(4);
|
||||||
this.handler = handler;
|
this.handler = handler;
|
||||||
@@ -84,6 +80,8 @@ class MasterSession extends SAMv3StreamSession implements SAMDatagramReceiver, S
|
|||||||
* @return null for success, or error message
|
* @return null for success, or error message
|
||||||
*/
|
*/
|
||||||
public synchronized String add(String nick, String style, Properties props) {
|
public synchronized String add(String nick, String style, Properties props) {
|
||||||
|
if (props.containsKey("DESTINATION"))
|
||||||
|
return "SESSION ADD may not contain DESTINATION";
|
||||||
SessionRecord rec = SAMv3Handler.sSessionsHash.get(nick);
|
SessionRecord rec = SAMv3Handler.sSessionsHash.get(nick);
|
||||||
if (rec != null || sessions.containsKey(nick))
|
if (rec != null || sessions.containsKey(nick))
|
||||||
return "Duplicate ID " + nick;
|
return "Duplicate ID " + nick;
|
||||||
@@ -103,9 +101,11 @@ class MasterSession extends SAMv3StreamSession implements SAMDatagramReceiver, S
|
|||||||
}
|
}
|
||||||
int listenProtocol;
|
int listenProtocol;
|
||||||
SAMMessageSess sess;
|
SAMMessageSess sess;
|
||||||
// temp
|
SAMv3Handler subhandler;
|
||||||
try {
|
try {
|
||||||
I2PSession isess = socketMgr.getSession();
|
I2PSession isess = socketMgr.getSession();
|
||||||
|
subhandler = new SAMv3Handler(handler.getClientSocket(), handler.verMajor,
|
||||||
|
handler.verMinor, handler.getBridge());
|
||||||
if (style.equals("RAW")) {
|
if (style.equals("RAW")) {
|
||||||
if (!props.containsKey("PORT"))
|
if (!props.containsKey("PORT"))
|
||||||
return "RAW subsession must specify PORT";
|
return "RAW subsession must specify PORT";
|
||||||
@@ -124,21 +124,32 @@ class MasterSession extends SAMv3StreamSession implements SAMDatagramReceiver, S
|
|||||||
return "Bad LISTEN_PROTOCOL " + spr;
|
return "Bad LISTEN_PROTOCOL " + spr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
sess = new SAMv3RawSession(nick, props, handler, isess, listenProtocol, listenPort, dgs);
|
SAMv3RawSession ssess = new SAMv3RawSession(nick, props, handler, isess, listenProtocol, listenPort, dgs);
|
||||||
|
subhandler.setSession(ssess);
|
||||||
|
sess = ssess;
|
||||||
} else if (style.equals("DATAGRAM")) {
|
} else if (style.equals("DATAGRAM")) {
|
||||||
if (!props.containsKey("PORT"))
|
if (!props.containsKey("PORT"))
|
||||||
return "DATAGRAM subsession must specify PORT";
|
return "DATAGRAM subsession must specify PORT";
|
||||||
listenProtocol = I2PSession.PROTO_DATAGRAM;
|
listenProtocol = I2PSession.PROTO_DATAGRAM;
|
||||||
sess = new SAMv3DatagramSession(nick, props, handler, isess, listenPort, dgs);
|
SAMv3DatagramSession ssess = new SAMv3DatagramSession(nick, props, handler, isess, listenPort, dgs);
|
||||||
|
subhandler.setSession(ssess);
|
||||||
|
sess = ssess;
|
||||||
} else if (style.equals("STREAM")) {
|
} else if (style.equals("STREAM")) {
|
||||||
listenProtocol = I2PSession.PROTO_STREAMING;
|
listenProtocol = I2PSession.PROTO_STREAMING;
|
||||||
// FIXME need something that hangs off an existing dest
|
// FIXME need something that hangs off an existing dest
|
||||||
sess = new SAMv3StreamSession(nick, props, handler, socketMgr, listenPort);
|
SAMv3StreamSession ssess = new SAMv3StreamSession(nick, props, handler, socketMgr, listenPort);
|
||||||
|
subhandler.setSession(ssess);
|
||||||
|
sess = ssess;
|
||||||
} else {
|
} else {
|
||||||
return "Unrecognized SESSION STYLE " + style;
|
return "Unrecognized SESSION STYLE " + style;
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (IOException e) {
|
||||||
// temp
|
return e.toString();
|
||||||
|
} catch (DataFormatException e) {
|
||||||
|
return e.toString();
|
||||||
|
} catch (SAMException e) {
|
||||||
|
return e.toString();
|
||||||
|
} catch (I2PSessionException e) {
|
||||||
return e.toString();
|
return e.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -148,8 +159,7 @@ class MasterSession extends SAMv3StreamSession implements SAMDatagramReceiver, S
|
|||||||
return "Duplicate protocol " + listenProtocol + " and port " + listenPort;
|
return "Duplicate protocol " + listenProtocol + " and port " + listenPort;
|
||||||
}
|
}
|
||||||
|
|
||||||
// add to session db and our map
|
rec = new SessionRecord(getDestination().toBase64(), props, subhandler);
|
||||||
rec = new SessionRecord(getDestination().toBase64(), props, handler);
|
|
||||||
try {
|
try {
|
||||||
if (!SAMv3Handler.sSessionsHash.put(nick, rec))
|
if (!SAMv3Handler.sSessionsHash.put(nick, rec))
|
||||||
return "Duplicate ID " + nick;
|
return "Duplicate ID " + nick;
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ import net.i2p.I2PAppContext;
|
|||||||
import net.i2p.I2PException;
|
import net.i2p.I2PException;
|
||||||
import net.i2p.client.I2PClient;
|
import net.i2p.client.I2PClient;
|
||||||
import net.i2p.client.I2PSession;
|
import net.i2p.client.I2PSession;
|
||||||
|
import net.i2p.client.I2PSessionException;
|
||||||
import net.i2p.client.streaming.I2PServerSocket;
|
import net.i2p.client.streaming.I2PServerSocket;
|
||||||
import net.i2p.client.streaming.I2PSocket;
|
import net.i2p.client.streaming.I2PSocket;
|
||||||
import net.i2p.client.streaming.I2PSocketManager;
|
import net.i2p.client.streaming.I2PSocketManager;
|
||||||
@@ -51,13 +52,9 @@ import net.i2p.util.Log;
|
|||||||
class SAMStreamSession implements SAMMessageSess {
|
class SAMStreamSession implements SAMMessageSess {
|
||||||
|
|
||||||
protected final Log _log;
|
protected final Log _log;
|
||||||
|
|
||||||
protected final static int SOCKET_HANDLER_BUF_SIZE = 32768;
|
protected final static int SOCKET_HANDLER_BUF_SIZE = 32768;
|
||||||
|
|
||||||
protected final SAMStreamReceiver recv;
|
protected final SAMStreamReceiver recv;
|
||||||
|
|
||||||
protected final SAMStreamSessionServer server;
|
protected final SAMStreamSessionServer server;
|
||||||
|
|
||||||
protected final I2PSocketManager socketMgr;
|
protected final I2PSocketManager socketMgr;
|
||||||
|
|
||||||
/** stream id (Long) to SAMStreamSessionSocketReader */
|
/** stream id (Long) to SAMStreamSessionSocketReader */
|
||||||
@@ -163,12 +160,13 @@ class SAMStreamSession implements SAMMessageSess {
|
|||||||
|
|
||||||
if (_log.shouldLog(Log.DEBUG))
|
if (_log.shouldLog(Log.DEBUG))
|
||||||
_log.debug("Creating I2PSocketManager...");
|
_log.debug("Creating I2PSocketManager...");
|
||||||
socketMgr = I2PSocketManagerFactory.createManager(destStream,
|
try {
|
||||||
i2cpHost,
|
// we do it this way so we get exceptions
|
||||||
i2cpPort,
|
socketMgr = I2PSocketManagerFactory.createDisconnectedManager(destStream,
|
||||||
allprops);
|
i2cpHost, i2cpPort, allprops);
|
||||||
if (socketMgr == null) {
|
socketMgr.getSession().connect();
|
||||||
throw new SAMException("Error creating I2PSocketManager");
|
} catch (I2PSessionException ise) {
|
||||||
|
throw new SAMException("Error creating I2PSocketManager: " + ise.getMessage(), ise);
|
||||||
}
|
}
|
||||||
|
|
||||||
socketMgr.addDisconnectListener(new DisconnectListener());
|
socketMgr.addDisconnectListener(new DisconnectListener());
|
||||||
|
|||||||
@@ -133,7 +133,31 @@ class SAMv3Handler extends SAMv1Handler
|
|||||||
Session getSession() {
|
Session getSession() {
|
||||||
return session;
|
return session;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* For subsessions created by MasterSession
|
||||||
|
* @since 0.9.25
|
||||||
|
*/
|
||||||
|
void setSession(SAMv3RawSession sess) {
|
||||||
|
rawSession = sess; session = sess;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* For subsessions created by MasterSession
|
||||||
|
* @since 0.9.25
|
||||||
|
*/
|
||||||
|
void setSession(SAMv3DatagramSession sess) {
|
||||||
|
datagramSession = sess; session = sess;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* For subsessions created by MasterSession
|
||||||
|
* @since 0.9.25
|
||||||
|
*/
|
||||||
|
void setSession(SAMv3StreamSession sess) {
|
||||||
|
streamSession = sess; session = sess;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void handle() {
|
public void handle() {
|
||||||
String msg = null;
|
String msg = null;
|
||||||
@@ -435,7 +459,16 @@ class SAMv3Handler extends SAMv1Handler
|
|||||||
Properties allProps = new Properties();
|
Properties allProps = new Properties();
|
||||||
allProps.putAll(i2cpProps);
|
allProps.putAll(i2cpProps);
|
||||||
allProps.putAll(props);
|
allProps.putAll(props);
|
||||||
|
|
||||||
|
if (style.equals("MASTER")) {
|
||||||
|
// We must put these here, as SessionRecord.getProps() makes a copy,
|
||||||
|
// and the socket manager is instantiated in the
|
||||||
|
// 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 {
|
try {
|
||||||
sSessionsHash.put( nick, new SessionRecord(dest, allProps, this) ) ;
|
sSessionsHash.put( nick, new SessionRecord(dest, allProps, this) ) ;
|
||||||
@@ -486,7 +519,7 @@ class SAMv3Handler extends SAMv1Handler
|
|||||||
} else if (opcode.equals("ADD") || opcode.equals("REMOVE")) {
|
} else if (opcode.equals("ADD") || opcode.equals("REMOVE")) {
|
||||||
// prevent trouble in finally block
|
// prevent trouble in finally block
|
||||||
ok = true;
|
ok = true;
|
||||||
if (streamSession != null || datagramSession != null || rawSession != null)
|
if (streamSession == null || datagramSession == null || rawSession == null)
|
||||||
return writeString("SESSION STATUS RESULT=I2P_ERROR MESSAGE=\"Not a MASTER session\"\n");
|
return writeString("SESSION STATUS RESULT=I2P_ERROR MESSAGE=\"Not a MASTER session\"\n");
|
||||||
MasterSession msess = (MasterSession) session;
|
MasterSession msess = (MasterSession) session;
|
||||||
String msg;
|
String msg;
|
||||||
@@ -512,14 +545,14 @@ class SAMv3Handler extends SAMv1Handler
|
|||||||
} catch (I2PSessionException e) {
|
} catch (I2PSessionException e) {
|
||||||
if (_log.shouldLog(Log.DEBUG))
|
if (_log.shouldLog(Log.DEBUG))
|
||||||
_log.debug("I2P error when instantiating session", e);
|
_log.debug("I2P error when instantiating session", e);
|
||||||
return writeString("SESSION STATUS RESULT=I2P_ERROR DESTINATION=" + dest + " MESSAGE=\"" + e.getMessage() + "\"\n");
|
return writeString("SESSION STATUS RESULT=I2P_ERROR MESSAGE=\"" + e.getMessage() + "\"\n");
|
||||||
} catch (SAMException e) {
|
} catch (SAMException e) {
|
||||||
if (_log.shouldLog(Log.INFO))
|
if (_log.shouldLog(Log.INFO))
|
||||||
_log.info("Funny SAM error", e);
|
_log.info("Funny SAM error", e);
|
||||||
return writeString("SESSION STATUS RESULT=I2P_ERROR DESTINATION=" + dest + " MESSAGE=\"" + e.getMessage() + "\"\n");
|
return writeString("SESSION STATUS RESULT=I2P_ERROR MESSAGE=\"" + e.getMessage() + "\"\n");
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
_log.error("Unexpected IOException", e);
|
_log.error("Unexpected IOException", e);
|
||||||
return writeString("SESSION STATUS RESULT=I2P_ERROR DESTINATION=" + dest + " MESSAGE=\"" + e.getMessage() + "\"\n");
|
return writeString("SESSION STATUS RESULT=I2P_ERROR MESSAGE=\"" + e.getMessage() + "\"\n");
|
||||||
} finally {
|
} finally {
|
||||||
// unregister the session if it has not been created
|
// unregister the session if it has not been created
|
||||||
if ( !ok && nick!=null ) {
|
if ( !ok && nick!=null ) {
|
||||||
@@ -566,23 +599,21 @@ class SAMv3Handler extends SAMv1Handler
|
|||||||
}
|
}
|
||||||
|
|
||||||
rec = sSessionsHash.get(nick);
|
rec = sSessionsHash.get(nick);
|
||||||
|
|
||||||
if ( rec==null ) {
|
if ( rec==null ) {
|
||||||
if (_log.shouldLog(Log.DEBUG))
|
if (_log.shouldLog(Log.DEBUG))
|
||||||
_log.debug("STREAM SESSION ID does not exist");
|
_log.debug("STREAM SESSION ID does not exist");
|
||||||
try {
|
try {
|
||||||
notifyStreamResult(true, "INVALID_ID", "STREAM SESSION ID does not exist");
|
notifyStreamResult(true, "INVALID_ID", "STREAM SESSION ID " + nick + " does not exist");
|
||||||
} catch (IOException e) {}
|
} catch (IOException e) {}
|
||||||
return false ;
|
return false ;
|
||||||
}
|
}
|
||||||
|
|
||||||
streamSession = rec.getHandler().streamSession ;
|
streamSession = rec.getHandler().streamSession ;
|
||||||
|
|
||||||
if (streamSession==null) {
|
if (streamSession==null) {
|
||||||
if (_log.shouldLog(Log.DEBUG))
|
if (_log.shouldLog(Log.DEBUG))
|
||||||
_log.debug("specified ID is not a stream session");
|
_log.debug("specified ID is not a stream session");
|
||||||
try {
|
try {
|
||||||
notifyStreamResult(true, "I2P_ERROR", "specified ID is not a STREAM session");
|
notifyStreamResult(true, "I2P_ERROR", "specified ID " + nick + " is not a STREAM session");
|
||||||
} catch (IOException e) {}
|
} catch (IOException e) {}
|
||||||
return false ;
|
return false ;
|
||||||
}
|
}
|
||||||
@@ -638,19 +669,19 @@ class SAMv3Handler extends SAMv1Handler
|
|||||||
} catch (DataFormatException e) {
|
} catch (DataFormatException e) {
|
||||||
if (_log.shouldLog(Log.DEBUG))
|
if (_log.shouldLog(Log.DEBUG))
|
||||||
_log.debug("Invalid destination in STREAM CONNECT message");
|
_log.debug("Invalid destination in STREAM CONNECT message");
|
||||||
notifyStreamResult ( verbose, "INVALID_KEY", null );
|
notifyStreamResult ( verbose, "INVALID_KEY", e.getMessage());
|
||||||
} catch (ConnectException e) {
|
} catch (ConnectException e) {
|
||||||
if (_log.shouldLog(Log.DEBUG))
|
if (_log.shouldLog(Log.DEBUG))
|
||||||
_log.debug("STREAM CONNECT failed", e);
|
_log.debug("STREAM CONNECT failed", e);
|
||||||
notifyStreamResult ( verbose, "CONNECTION_REFUSED", null );
|
notifyStreamResult ( verbose, "CONNECTION_REFUSED", e.getMessage());
|
||||||
} catch (NoRouteToHostException e) {
|
} catch (NoRouteToHostException e) {
|
||||||
if (_log.shouldLog(Log.DEBUG))
|
if (_log.shouldLog(Log.DEBUG))
|
||||||
_log.debug("STREAM CONNECT failed", e);
|
_log.debug("STREAM CONNECT failed", e);
|
||||||
notifyStreamResult ( verbose, "CANT_REACH_PEER", null );
|
notifyStreamResult ( verbose, "CANT_REACH_PEER", e.getMessage());
|
||||||
} catch (InterruptedIOException e) {
|
} catch (InterruptedIOException e) {
|
||||||
if (_log.shouldLog(Log.DEBUG))
|
if (_log.shouldLog(Log.DEBUG))
|
||||||
_log.debug("STREAM CONNECT failed", e);
|
_log.debug("STREAM CONNECT failed", e);
|
||||||
notifyStreamResult ( verbose, "TIMEOUT", null );
|
notifyStreamResult ( verbose, "TIMEOUT", e.getMessage());
|
||||||
} catch (I2PException e) {
|
} catch (I2PException e) {
|
||||||
if (_log.shouldLog(Log.DEBUG))
|
if (_log.shouldLog(Log.DEBUG))
|
||||||
_log.debug("STREAM CONNECT failed", e);
|
_log.debug("STREAM CONNECT failed", e);
|
||||||
@@ -702,7 +733,7 @@ class SAMv3Handler extends SAMv1Handler
|
|||||||
} catch (SAMException e) {
|
} catch (SAMException e) {
|
||||||
if (_log.shouldLog(Log.DEBUG))
|
if (_log.shouldLog(Log.DEBUG))
|
||||||
_log.debug("STREAM ACCEPT failed", e);
|
_log.debug("STREAM ACCEPT failed", e);
|
||||||
notifyStreamResult ( verbose, "ALREADY_ACCEPTING", null );
|
notifyStreamResult ( verbose, "ALREADY_ACCEPTING", e.getMessage());
|
||||||
}
|
}
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
}
|
}
|
||||||
@@ -710,6 +741,11 @@ class SAMv3Handler extends SAMv1Handler
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param verbose if false, does nothing
|
||||||
|
* @param result non-null
|
||||||
|
* @param message may be null
|
||||||
|
*/
|
||||||
public void notifyStreamResult(boolean verbose, String result, String message) throws IOException {
|
public void notifyStreamResult(boolean verbose, String result, String message) throws IOException {
|
||||||
if (!verbose) return ;
|
if (!verbose) return ;
|
||||||
String msgString = createMessageString(message);
|
String msgString = createMessageString(message);
|
||||||
|
|||||||
@@ -42,6 +42,10 @@ class SessionRecord {
|
|||||||
return m_dest;
|
return m_dest;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Warning - returns a copy.
|
||||||
|
* @return a copy
|
||||||
|
*/
|
||||||
synchronized public Properties getProps()
|
synchronized public Properties getProps()
|
||||||
{
|
{
|
||||||
Properties p = new Properties();
|
Properties p = new Properties();
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ public class SAMEventHandler extends SAMClientEventListenerImpl {
|
|||||||
private String _version;
|
private String _version;
|
||||||
private final Object _helloLock = new Object();
|
private final Object _helloLock = new Object();
|
||||||
private Boolean _sessionCreateOk;
|
private Boolean _sessionCreateOk;
|
||||||
|
private Boolean _sessionAddOk;
|
||||||
private Boolean _streamStatusOk;
|
private Boolean _streamStatusOk;
|
||||||
private final Object _sessionCreateLock = new Object();
|
private final Object _sessionCreateLock = new Object();
|
||||||
private final Object _namingReplyLock = new Object();
|
private final Object _namingReplyLock = new Object();
|
||||||
@@ -41,13 +42,19 @@ public class SAMEventHandler extends SAMClientEventListenerImpl {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** may be called twice, first for CREATE and second for ADD */
|
||||||
@Override
|
@Override
|
||||||
public void sessionStatusReceived(String result, String destination, String msg) {
|
public void sessionStatusReceived(String result, String destination, String msg) {
|
||||||
synchronized (_sessionCreateLock) {
|
synchronized (_sessionCreateLock) {
|
||||||
|
Boolean ok;
|
||||||
if (SAMReader.SAMClientEventListener.SESSION_STATUS_OK.equals(result))
|
if (SAMReader.SAMClientEventListener.SESSION_STATUS_OK.equals(result))
|
||||||
_sessionCreateOk = Boolean.TRUE;
|
ok = Boolean.TRUE;
|
||||||
else
|
else
|
||||||
_sessionCreateOk = Boolean.FALSE;
|
ok = Boolean.FALSE;
|
||||||
|
if (_sessionCreateOk == null)
|
||||||
|
_sessionCreateOk = ok;
|
||||||
|
else if (_sessionAddOk == null)
|
||||||
|
_sessionAddOk = ok;
|
||||||
_sessionCreateLock.notifyAll();
|
_sessionCreateLock.notifyAll();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -120,6 +127,25 @@ public class SAMEventHandler extends SAMClientEventListenerImpl {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wait for the session to be added, returning true if everything went ok
|
||||||
|
*
|
||||||
|
* @return true if everything ok
|
||||||
|
* @since 0.9.25
|
||||||
|
*/
|
||||||
|
public boolean waitForSessionAddReply() {
|
||||||
|
while (true) {
|
||||||
|
try {
|
||||||
|
synchronized (_sessionCreateLock) {
|
||||||
|
if (_sessionAddOk == null)
|
||||||
|
_sessionCreateLock.wait();
|
||||||
|
else
|
||||||
|
return _sessionAddOk.booleanValue();
|
||||||
|
}
|
||||||
|
} catch (InterruptedException ie) { return false; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Wait for the stream to be created, returning true if everything went ok
|
* Wait for the stream to be created, returning true if everything went ok
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -55,14 +55,17 @@ public class SAMStreamSend {
|
|||||||
private static I2PSSLSocketFactory _sslSocketFactory;
|
private static I2PSSLSocketFactory _sslSocketFactory;
|
||||||
|
|
||||||
private static final int STREAM=0, DG=1, V1DG=2, RAW=3, V1RAW=4;
|
private static final int STREAM=0, DG=1, V1DG=2, RAW=3, V1RAW=4;
|
||||||
private static final String USAGE = "Usage: SAMStreamSend [-s] [-m mode] [-v version] [-b samHost] [-p samPort] [-o opt=val] [-u user] [-w password] peerDestFile dataDir\n" +
|
private static final int MASTER=8;
|
||||||
|
private static final String USAGE = "Usage: SAMStreamSend [-s] [-x] [-m mode] [-v version] [-b samHost] [-p samPort] [-o opt=val] [-u user] [-w password] peerDestFile dataDir\n" +
|
||||||
" modes: stream: 0; datagram: 1; v1datagram: 2; raw: 3; v1raw: 4\n" +
|
" modes: stream: 0; datagram: 1; v1datagram: 2; raw: 3; v1raw: 4\n" +
|
||||||
" -s: use SSL\n" +
|
" -s: use SSL\n" +
|
||||||
|
" -x: use master session (forces -v 3.3)\n" +
|
||||||
" multiple -o session options are allowed";
|
" multiple -o session options are allowed";
|
||||||
|
|
||||||
public static void main(String args[]) {
|
public static void main(String args[]) {
|
||||||
Getopt g = new Getopt("SAM", args, "sb:m:o:p:u:v:w:");
|
Getopt g = new Getopt("SAM", args, "sxb:m:o:p:u:v:w:");
|
||||||
boolean isSSL = false;
|
boolean isSSL = false;
|
||||||
|
boolean isMaster = false;
|
||||||
int mode = STREAM;
|
int mode = STREAM;
|
||||||
String version = "1.0";
|
String version = "1.0";
|
||||||
String host = "127.0.0.1";
|
String host = "127.0.0.1";
|
||||||
@@ -77,6 +80,10 @@ public class SAMStreamSend {
|
|||||||
isSSL = true;
|
isSSL = true;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 'x':
|
||||||
|
isMaster = true;
|
||||||
|
break;
|
||||||
|
|
||||||
case 'm':
|
case 'm':
|
||||||
mode = Integer.parseInt(g.getOptarg());
|
mode = Integer.parseInt(g.getOptarg());
|
||||||
if (mode < 0 || mode > V1RAW) {
|
if (mode < 0 || mode > V1RAW) {
|
||||||
@@ -123,6 +130,10 @@ public class SAMStreamSend {
|
|||||||
System.err.println(USAGE);
|
System.err.println(USAGE);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (isMaster) {
|
||||||
|
mode += MASTER;
|
||||||
|
version = "3.3";
|
||||||
|
}
|
||||||
if ((user == null && password != null) ||
|
if ((user == null && password != null) ||
|
||||||
(user != null && password == null)) {
|
(user != null && password == null)) {
|
||||||
System.err.println("both user and password or neither");
|
System.err.println("both user and password or neither");
|
||||||
@@ -162,6 +173,8 @@ public class SAMStreamSend {
|
|||||||
_log.debug("Reader created");
|
_log.debug("Reader created");
|
||||||
OutputStream out = sock.getOutputStream();
|
OutputStream out = sock.getOutputStream();
|
||||||
String ourDest = handshake(out, version, true, eventHandler, mode, user, password, sessionOpts);
|
String ourDest = handshake(out, version, true, eventHandler, mode, user, password, sessionOpts);
|
||||||
|
if (mode >= MASTER)
|
||||||
|
mode -= MASTER;
|
||||||
if (ourDest == null)
|
if (ourDest == null)
|
||||||
throw new IOException("handshake failed");
|
throw new IOException("handshake failed");
|
||||||
if (_log.shouldLog(Log.DEBUG))
|
if (_log.shouldLog(Log.DEBUG))
|
||||||
@@ -230,7 +243,10 @@ public class SAMStreamSend {
|
|||||||
return sock;
|
return sock;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @return our b64 dest or null */
|
/**
|
||||||
|
* @param isMaster is this the control socket
|
||||||
|
* @return our b64 dest or null
|
||||||
|
*/
|
||||||
private String handshake(OutputStream samOut, String version, boolean isMaster,
|
private String handshake(OutputStream samOut, String version, boolean isMaster,
|
||||||
SAMEventHandler eventHandler, int mode, String user, String password,
|
SAMEventHandler eventHandler, int mode, String user, String password,
|
||||||
String opts) {
|
String opts) {
|
||||||
@@ -261,6 +277,16 @@ public class SAMStreamSend {
|
|||||||
_v3ID = "xx€€xx" + _v3ID;
|
_v3ID = "xx€€xx" + _v3ID;
|
||||||
_conOptions = "ID=" + _v3ID;
|
_conOptions = "ID=" + _v3ID;
|
||||||
}
|
}
|
||||||
|
boolean masterMode; // are we using v3.3 master session
|
||||||
|
String command;
|
||||||
|
if (mode >= MASTER) {
|
||||||
|
masterMode = true;
|
||||||
|
command = "ADD";
|
||||||
|
mode -= MASTER;
|
||||||
|
} else {
|
||||||
|
masterMode = false;
|
||||||
|
command = "CREATE DESTINATION=TRANSIENT";
|
||||||
|
}
|
||||||
String style;
|
String style;
|
||||||
if (mode == STREAM)
|
if (mode == STREAM)
|
||||||
style = "STREAM";
|
style = "STREAM";
|
||||||
@@ -268,16 +294,33 @@ public class SAMStreamSend {
|
|||||||
style = "DATAGRAM";
|
style = "DATAGRAM";
|
||||||
else
|
else
|
||||||
style = "RAW";
|
style = "RAW";
|
||||||
String req = "SESSION CREATE STYLE=" + style + " DESTINATION=TRANSIENT " + _conOptions + ' ' + opts + '\n';
|
|
||||||
|
if (masterMode) {
|
||||||
|
String req = "SESSION CREATE DESTINATION=TRANSIENT STYLE=MASTER ID=master " + opts + '\n';
|
||||||
|
samOut.write(req.getBytes("UTF-8"));
|
||||||
|
samOut.flush();
|
||||||
|
if (_log.shouldLog(Log.DEBUG))
|
||||||
|
_log.debug("SESSION CREATE STYLE=MASTER sent");
|
||||||
|
boolean ok = eventHandler.waitForSessionCreateReply();
|
||||||
|
if (!ok)
|
||||||
|
throw new IOException("SESSION CREATE STYLE=MASTER failed");
|
||||||
|
if (_log.shouldLog(Log.DEBUG))
|
||||||
|
_log.debug("SESSION CREATE STYLE=MASTER reply found: " + ok);
|
||||||
|
}
|
||||||
|
String req = "SESSION " + command + " STYLE=" + style + ' ' + _conOptions + ' ' + opts + '\n';
|
||||||
samOut.write(req.getBytes("UTF-8"));
|
samOut.write(req.getBytes("UTF-8"));
|
||||||
samOut.flush();
|
samOut.flush();
|
||||||
if (_log.shouldLog(Log.DEBUG))
|
if (_log.shouldLog(Log.DEBUG))
|
||||||
_log.debug("Session create sent");
|
_log.debug("SESSION " + command + " sent");
|
||||||
boolean ok = eventHandler.waitForSessionCreateReply();
|
boolean ok;
|
||||||
|
if (masterMode)
|
||||||
|
ok = eventHandler.waitForSessionAddReply();
|
||||||
|
else
|
||||||
|
ok = eventHandler.waitForSessionCreateReply();
|
||||||
if (!ok)
|
if (!ok)
|
||||||
throw new IOException("Session create failed");
|
throw new IOException("SESSION " + command + " failed");
|
||||||
if (_log.shouldLog(Log.DEBUG))
|
if (_log.shouldLog(Log.DEBUG))
|
||||||
_log.debug("Session create reply found: " + ok);
|
_log.debug("SESSION " + command + " reply found: " + ok);
|
||||||
|
|
||||||
req = "NAMING LOOKUP NAME=ME\n";
|
req = "NAMING LOOKUP NAME=ME\n";
|
||||||
samOut.write(req.getBytes("UTF-8"));
|
samOut.write(req.getBytes("UTF-8"));
|
||||||
|
|||||||
Reference in New Issue
Block a user