package net.i2p.sam.client;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import net.i2p.I2PAppContext;
import net.i2p.util.Log;
/**
* Simple helper implementation of a the SAMClientEventListener
*
*/
public class SAMEventHandler extends SAMClientEventListenerImpl {
//private I2PAppContext _context;
private final Log _log;
private Boolean _helloOk;
private String _version;
private final Object _helloLock = new Object();
private Boolean _sessionCreateOk;
private Boolean _sessionAddOk;
private Boolean _streamStatusOk;
private final Object _sessionCreateLock = new Object();
private final Object _namingReplyLock = new Object();
private final Object _streamStatusLock = new Object();
private final Map<String,String> _namingReplies = new HashMap<String,String>();
public SAMEventHandler(I2PAppContext ctx) {
//_context = ctx;
_log = ctx.logManager().getLog(getClass());
}
@Override
public void helloReplyReceived(boolean ok, String version) {
synchronized (_helloLock) {
if (ok)
_helloOk = Boolean.TRUE;
else
_helloOk = Boolean.FALSE;
_version = version;
_helloLock.notifyAll();
}
}
/** may be called twice, first for CREATE and second for ADD */
@Override
public void sessionStatusReceived(String result, String destination, String msg) {
synchronized (_sessionCreateLock) {
Boolean ok;
if (SAMReader.SAMClientEventListener.SESSION_STATUS_OK.equals(result))
ok = Boolean.TRUE;
else
ok = Boolean.FALSE;
if (_sessionCreateOk == null)
_sessionCreateOk = ok;
else if (_sessionAddOk == null)
_sessionAddOk = ok;
_sessionCreateLock.notifyAll();
}
}
@Override
public void namingReplyReceived(String name, String result, String value, String msg) {
synchronized (_namingReplyLock) {
if (SAMReader.SAMClientEventListener.NAMING_REPLY_OK.equals(result))
_namingReplies.put(name, value);
else
_namingReplies.put(name, result);
_namingReplyLock.notifyAll();
}
}
@Override
public void streamStatusReceived(String result, String id, String message) {
synchronized (_streamStatusLock) {
if (SAMReader.SAMClientEventListener.SESSION_STATUS_OK.equals(result))
_streamStatusOk = Boolean.TRUE;
else
_streamStatusOk = Boolean.FALSE;
_streamStatusLock.notifyAll();
}
}
@Override
public void unknownMessageReceived(String major, String minor, Properties params) {
_log.error("Unhandled message: [" + major + "] [" + minor + "] [" + params + "]");
}
//
// blocking lookup calls below
//
/**
* Wait for the connection to be established, returning the server version if everything
* went ok
* @return SAM server version if everything ok, or null on failure
*/
public String waitForHelloReply() {
while (true) {
try {
synchronized (_helloLock) {
if (_helloOk == null)
_helloLock.wait();
else
return _helloOk.booleanValue() ? _version : null;
}
} catch (InterruptedException ie) { return null; }
}
}
/**
* Wait for the session to be created, returning true if everything went ok
*
* @return true if everything ok
*/
public boolean waitForSessionCreateReply() {
while (true) {
try {
synchronized (_sessionCreateLock) {
if (_sessionCreateOk == null)
_sessionCreateLock.wait();
else
return _sessionCreateOk.booleanValue();
}
} catch (InterruptedException ie) { return false; }
}
}
/**
* 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
*
* @return true if everything ok
*/
public boolean waitForStreamStatusReply() {
while (true) {
try {
synchronized (_streamStatusLock) {
if (_streamStatusOk == null)
_streamStatusLock.wait();
else
return _streamStatusOk.booleanValue();
}
} catch (InterruptedException ie) { return false; }
}
}
/**
* Return the destination found matching the name, or null if the key was
* not able to be retrieved.
*
* @param name name to be looked for, or "ME"
* @return destination found matching the name, or null
*/
public String waitForNamingReply(String name) {
while (true) {
try {
synchronized (_namingReplyLock) {
String val = _namingReplies.remove(name);
if (val == null) {
_namingReplyLock.wait();
} else {
if (SAMReader.SAMClientEventListener.NAMING_REPLY_INVALID_KEY.equals(val))
return null;
else if (SAMReader.SAMClientEventListener.NAMING_REPLY_KEY_NOT_FOUND.equals(val))
return null;
else
return val;
}
}
} catch (InterruptedException ie) { return null; }
}
}
}