use of net.i2p.client.I2PSessionException in project i2p.i2p by i2p.
the class I2CPMessageProducer method sendMessage.
/**
* Package up and send the payload to the router for delivery
*
* @param nonce 0 to 0xffffffff; if 0, the router will not reply with a MessageStatusMessage
* @since 0.9.2
*/
public void sendMessage(I2PSessionImpl session, Destination dest, long nonce, byte[] payload, SendMessageOptions options) throws I2PSessionException {
long expires = options.getTime();
if (!updateBps(payload.length, expires))
// drop the message... send fail notification?
return;
SendMessageMessage msg = new SendMessageExpiresMessage(options);
msg.setDestination(dest);
SessionId sid = session.getSessionId();
if (sid == null) {
_log.error(session.toString() + " send message w/o session", new Exception());
return;
}
msg.setSessionId(sid);
msg.setNonce(nonce);
Payload data = createPayload(dest, payload, null, null, null, null);
msg.setPayload(data);
session.sendMessage(msg);
}
use of net.i2p.client.I2PSessionException in project i2p.i2p by i2p.
the class I2PSessionImpl method addSubsession.
/**
* Router must be connected or was connected... for now.
*
* @return a new subsession, non-null
* @param privateKeyStream null for transient, if non-null must have same encryption keys as primary session
* and different signing keys
* @param opts subsession options if any, may be null
* @since 0.9.21
*/
public I2PSession addSubsession(InputStream privateKeyStream, Properties opts) throws I2PSessionException {
if (!_routerSupportsSubsessions)
throw new I2PSessionException("Router does not support subsessions");
SubSession sub;
synchronized (_subsessionLock) {
if (_subsessions.size() > _subsessionMap.size())
throw new I2PSessionException("Subsession request already pending");
sub = new SubSession(this, privateKeyStream, opts);
for (SubSession ss : _subsessions) {
if (ss.getDecryptionKey().equals(sub.getDecryptionKey()) && ss.getPrivateKey().equals(sub.getPrivateKey())) {
throw new I2PSessionException("Dup subsession");
}
}
_subsessions.add(sub);
}
synchronized (_stateLock) {
if (_state == State.OPEN) {
_producer.connect(sub);
}
// else will be called in connect()
}
return sub;
}
use of net.i2p.client.I2PSessionException in project i2p.i2p by i2p.
the class I2PSessionImpl method connect.
/**
* Connect to the router and establish a session. This call blocks until
* a session is granted.
*
* Should be threadsafe, other threads will block until complete.
* Disconnect / destroy from another thread may be called simultaneously and
* will (should?) interrupt the connect.
*
* Connecting a primary session will not automatically connect subsessions.
* Connecting a subsession will automatically connect the primary session
* if not previously connected.
*
* @throws I2PSessionException if there is a configuration error or the router is
* not reachable
*/
public void connect() throws I2PSessionException {
synchronized (_stateLock) {
boolean wasOpening = false;
boolean loop = true;
while (loop) {
switch(_state) {
case INIT:
loop = false;
break;
case CLOSED:
if (wasOpening)
throw new I2PSessionException("connect by other thread failed");
loop = false;
break;
case OPENING:
case GOTDATE:
wasOpening = true;
try {
_stateLock.wait(10 * 1000);
} catch (InterruptedException ie) {
throw new I2PSessionException("Interrupted", ie);
}
break;
case CLOSING:
throw new I2PSessionException("close in progress");
case OPEN:
return;
}
}
changeState(State.OPENING);
}
_availabilityNotifier.stopNotifying();
if ((_options != null) && (I2PClient.PROP_RELIABILITY_GUARANTEED.equals(_options.getProperty(I2PClient.PROP_RELIABILITY, I2PClient.PROP_RELIABILITY_BEST_EFFORT)))) {
if (_log.shouldLog(Log.ERROR))
_log.error("I2CP guaranteed delivery mode has been removed, using best effort.");
}
boolean success = false;
long startConnect = _context.clock().now();
try {
// protect w/ closeSocket()
synchronized (_stateLock) {
// If we are in the router JVM, connect using the internal queue
if (_context.isRouterContext()) {
// _socket and _writer remain null
InternalClientManager mgr = _context.internalClientManager();
if (mgr == null)
throw new I2PSessionException("Router is not ready for connections");
// the following may throw an I2PSessionException
_queue = mgr.connect();
_reader = new QueuedI2CPMessageReader(_queue, this);
} else {
if (SystemVersion.isAndroid() && _options.getProperty(PROP_DOMAIN_SOCKET) != null) {
try {
Class<?> clazz = Class.forName("net.i2p.client.DomainSocketFactory");
Constructor<?> ctor = clazz.getDeclaredConstructor(I2PAppContext.class);
Object fact = ctor.newInstance(_context);
Method createSocket = clazz.getDeclaredMethod("createSocket", String.class);
try {
_socket = (Socket) createSocket.invoke(fact, _options.getProperty(PROP_DOMAIN_SOCKET));
} catch (InvocationTargetException e) {
throw new I2PSessionException("Cannot create domain socket", e);
}
} catch (ClassNotFoundException e) {
throw new I2PSessionException("Cannot load DomainSocketFactory", e);
} catch (NoSuchMethodException e) {
throw new I2PSessionException("Cannot load DomainSocketFactory", e);
} catch (InstantiationException e) {
throw new I2PSessionException("Cannot load DomainSocketFactory", e);
} catch (IllegalAccessException e) {
throw new I2PSessionException("Cannot load DomainSocketFactory", e);
} catch (InvocationTargetException e) {
throw new I2PSessionException("Cannot load DomainSocketFactory", e);
}
} else if (Boolean.parseBoolean(_options.getProperty(PROP_ENABLE_SSL))) {
try {
I2PSSLSocketFactory fact = new I2PSSLSocketFactory(_context, false, "certificates/i2cp");
_socket = fact.createSocket(_hostname, _portNum);
_socket.setKeepAlive(true);
} catch (GeneralSecurityException gse) {
IOException ioe = new IOException("SSL Fail");
ioe.initCause(gse);
throw ioe;
}
} else {
_socket = new Socket(_hostname, _portNum);
_socket.setKeepAlive(true);
}
// _socket.setSoTimeout(1000000); // Uhmmm we could really-really use a real timeout, and handle it.
OutputStream out = _socket.getOutputStream();
out.write(I2PClient.PROTOCOL_BYTE);
out.flush();
_writer = new ClientWriterRunner(out, this);
_writer.startWriting();
InputStream in = new BufferedInputStream(_socket.getInputStream(), BUF_SIZE);
_reader = new I2CPMessageReader(in, this);
}
}
if (_log.shouldLog(Log.DEBUG))
_log.debug(getPrefix() + "before startReading");
_reader.startReading();
if (_log.shouldLog(Log.DEBUG))
_log.debug(getPrefix() + "Before getDate");
Properties auth = null;
if ((!_context.isRouterContext()) && _options.containsKey(PROP_USER) && _options.containsKey(PROP_PW)) {
// Only supported by routers 0.9.11 or higher, but we don't know the version yet.
// Auth will also be sent in the SessionConfig.
auth = new OrderedProperties();
auth.setProperty(PROP_USER, _options.getProperty(PROP_USER));
auth.setProperty(PROP_PW, _options.getProperty(PROP_PW));
}
sendMessage_unchecked(new GetDateMessage(CoreVersion.VERSION, auth));
waitForDate();
if (_log.shouldLog(Log.DEBUG))
_log.debug(getPrefix() + "Before producer.connect()");
_producer.connect(this);
if (_log.shouldLog(Log.DEBUG))
_log.debug(getPrefix() + "After producer.connect()");
// wait until we have created a lease set
int waitcount = 0;
while (_leaseSet == null) {
if (waitcount++ > 5 * 60) {
throw new IOException("No tunnels built after waiting 5 minutes. Your network connection may be down, or there is severe network congestion.");
}
synchronized (_leaseSetWait) {
// InterruptedException caught below
_leaseSetWait.wait(1000);
}
// if we got a disconnect message while waiting
if (isClosed())
throw new IOException("Disconnected from router while waiting for tunnels");
}
if (_log.shouldLog(Log.INFO)) {
long connected = _context.clock().now();
_log.info(getPrefix() + "Lease set created with inbound tunnels after " + (connected - startConnect) + "ms - ready to participate in the network!");
}
Thread notifier = new I2PAppThread(_availabilityNotifier, "ClientNotifier " + getPrefix(), true);
notifier.start();
startIdleMonitor();
startVerifyUsage();
success = true;
// now send CreateSessionMessages for all subsessions, one at a time, must wait for each response
synchronized (_subsessionLock) {
for (SubSession ss : _subsessions) {
if (_log.shouldLog(Log.INFO))
_log.info(getPrefix() + "Connecting subsession " + ss);
_producer.connect(ss);
}
}
} catch (InterruptedException ie) {
throw new I2PSessionException("Interrupted", ie);
} catch (UnknownHostException uhe) {
throw new I2PSessionException(getPrefix() + "Cannot connect to the router on " + _hostname + ':' + _portNum, uhe);
} catch (IOException ioe) {
// Generate the best error message as this will be logged
String msg;
if (_context.isRouterContext())
msg = "Failed to build tunnels";
else if (SystemVersion.isAndroid() && _options.getProperty(PROP_DOMAIN_SOCKET) != null)
msg = "Failed to bind to the router on " + _options.getProperty(PROP_DOMAIN_SOCKET) + " and build tunnels";
else
msg = "Cannot connect to the router on " + _hostname + ':' + _portNum + " and build tunnels";
throw new I2PSessionException(getPrefix() + msg, ioe);
} finally {
if (success) {
changeState(State.OPEN);
} else {
_availabilityNotifier.stopNotifying();
synchronized (_stateLock) {
changeState(State.CLOSING);
try {
_producer.disconnect(this);
} catch (I2PSessionException ipe) {
}
closeSocket();
}
}
}
}
use of net.i2p.client.I2PSessionException in project i2p.i2p by i2p.
the class I2PSimpleSession method connect.
/**
* Connect to the router and establish a session. This call blocks until
* a session is granted.
*
* NOT threadsafe, do not call from multiple threads.
*
* @throws I2PSessionException if there is a configuration error or the router is
* not reachable
*/
@Override
public void connect() throws I2PSessionException {
changeState(State.OPENING);
boolean success = false;
try {
// protect w/ closeSocket()
synchronized (_stateLock) {
// If we are in the router JVM, connect using the interal queue
if (_context.isRouterContext()) {
// _socket and _writer remain null
InternalClientManager mgr = _context.internalClientManager();
if (mgr == null)
throw new I2PSessionException("Router is not ready for connections");
// the following may throw an I2PSessionException
_queue = mgr.connect();
_reader = new QueuedI2CPMessageReader(_queue, this);
_reader.startReading();
} else {
if (Boolean.parseBoolean(getOptions().getProperty(PROP_ENABLE_SSL))) {
try {
I2PSSLSocketFactory fact = new I2PSSLSocketFactory(_context, false, "certificates/i2cp");
_socket = fact.createSocket(_hostname, _portNum);
} catch (GeneralSecurityException gse) {
IOException ioe = new IOException("SSL Fail");
ioe.initCause(gse);
throw ioe;
}
} else {
_socket = new Socket(_hostname, _portNum);
}
_socket.setKeepAlive(true);
OutputStream out = _socket.getOutputStream();
out.write(I2PClient.PROTOCOL_BYTE);
out.flush();
_writer = new ClientWriterRunner(out, this);
_writer.startWriting();
InputStream in = new BufferedInputStream(_socket.getInputStream(), BUF_SIZE);
_reader = new I2CPMessageReader(in, this);
_reader.startReading();
}
}
// must be out of synch block for writer to get unblocked
if (!_context.isRouterContext()) {
Properties opts = getOptions();
// support the AuthMessage
if ((!opts.containsKey(PROP_USER)) && (!opts.containsKey(PROP_PW))) {
// auto-add auth if not set in the options
String configUser = _context.getProperty(PROP_USER);
String configPW = _context.getProperty(PROP_PW);
if (configUser != null && configPW != null) {
opts.setProperty(PROP_USER, configUser);
opts.setProperty(PROP_PW, configPW);
}
}
if (opts.containsKey(PROP_USER) && opts.containsKey(PROP_PW)) {
Properties auth = new OrderedProperties();
auth.setProperty(PROP_USER, opts.getProperty(PROP_USER));
auth.setProperty(PROP_PW, opts.getProperty(PROP_PW));
sendMessage_unchecked(new GetDateMessage(CoreVersion.VERSION, auth));
} else {
// we must now send a GetDate even in SimpleSession, or we won't know
// what version we are talking with and cannot use HostLookup
sendMessage_unchecked(new GetDateMessage(CoreVersion.VERSION));
}
waitForDate();
}
// we do not receive payload messages, so we do not need an AvailabilityNotifier
// ... or an Idle timer, or a VerifyUsage
success = true;
if (_log.shouldLog(Log.INFO))
_log.info(getPrefix() + " simple session connected");
} catch (InterruptedException ie) {
throw new I2PSessionException("Interrupted", ie);
} catch (UnknownHostException uhe) {
throw new I2PSessionException(getPrefix() + "Cannot connect to the router on " + _hostname + ':' + _portNum, uhe);
} catch (IOException ioe) {
// Generate the best error message as this will be logged
String msg;
if (_context.isRouterContext())
msg = "Failed internal router binding";
else if (SystemVersion.isAndroid() && Boolean.parseBoolean(getOptions().getProperty(PROP_DOMAIN_SOCKET)))
msg = "Failed to bind to the router";
else
msg = "Cannot connect to the router on " + _hostname + ':' + _portNum;
throw new I2PSessionException(getPrefix() + msg, ioe);
} finally {
changeState(success ? State.OPEN : State.CLOSED);
}
}
use of net.i2p.client.I2PSessionException in project i2p.i2p by i2p.
the class DisconnectMessageHandler method handleMessage.
public void handleMessage(I2CPMessage message, I2PSessionImpl session) {
if (_log.shouldLog(Log.DEBUG))
_log.debug("Handle message " + message);
String reason = ((DisconnectMessage) message).getReason();
session.propogateError(reason, new I2PSessionException("Disconnect Message received: " + reason));
session.destroySession(false);
if (reason.contains("restart")) {
Thread t = new I2PAppThread(new Reconnector(session), "Reconnect " + session, true);
t.start();
}
}
Aggregations