I2P Address: [http://git.idk.i2p]

Skip to content
Snippets Groups Projects
Commit d4bf2523 authored by zzz's avatar zzz
Browse files

* I2CP:

      - Append I2CP Version information to the Get/Set Date Messages,
        so that both the router and client are aware of the other side's version,
        and future protocol changes will be easier to implement.
        Previously, router version information was not available to the client,
        so when router and client were in different JVMs,
        old clients would work with new routers
        but new clients would not work with old routers.
        After this change, we can design future changes so that new clients
        will work with old routers.
        This is an enhancement to the old protocol version byte sent by the client,
        which we have never changed and probably never will.
      - Prevent a client from setting the router's clock
      - Javadocs
parent acb4bac5
No related branches found
No related tags found
No related merge requests found
......@@ -130,14 +130,19 @@ public interface I2PSession {
/** Receive a message that the router has notified the client about, returning
* the payload.
* This may only be called once for a given msgId (until the counter wraps)
*
* @param msgId message to fetch
* @return unencrypted body of the message
* @return unencrypted body of the message, or null if not found
*/
public byte[] receiveMessage(int msgId) throws I2PSessionException;
/** Instruct the router that the message received was abusive (including how
* abusive on a 1-100 scale) in the hopes the router can do something to
* minimize receiving abusive messages like that in the future.
*
* Unused. Not fully implemented.
*
* @param msgId message that was abusive (or -1 for not message related)
* @param severity how abusive
*/
......
......@@ -25,6 +25,7 @@ import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.LinkedBlockingQueue;
import net.i2p.CoreVersion;
import net.i2p.I2PAppContext;
import net.i2p.data.DataFormatException;
import net.i2p.data.Destination;
......@@ -359,7 +360,7 @@ abstract class I2PSessionImpl implements I2PSession, I2CPMessageReader.I2CPMessa
if (_log.shouldLog(Log.DEBUG)) _log.debug(getPrefix() + "before startReading");
_reader.startReading();
if (_log.shouldLog(Log.DEBUG)) _log.debug(getPrefix() + "Before getDate");
sendMessage(new GetDateMessage());
sendMessage(new GetDateMessage(CoreVersion.VERSION));
if (_log.shouldLog(Log.DEBUG)) _log.debug(getPrefix() + "After getDate / begin waiting for a response");
int waitcount = 0;
while (!_dateReceived) {
......
......@@ -13,11 +13,25 @@ package net.i2p.client;
* Define a means for the router to asynchronously notify the client that a
* new message is available or the router is under attack.
*
* A client must implement and register this via addSessionListener()
* to receive messages.
*
* If you wish to get notification of the protocol, from port, and to port,
* or wish to get notification of certain protocols and ports only,
* you must use I2PSessionMuxedListener and addMuxedSessionListener() instead.
*
* @author jrandom
*/
public interface I2PSessionListener {
/** Instruct the client that the given session has received a message with
* size # of bytes.
*
* After this is called, the client should call receiveMessage(msgId).
* There is currently no method for the client to reject the message.
* If the client does not call receiveMessage() within a timeout period
* (currently 30 seconds), the session will delete the message and
* log an error.
*
* @param session session to notify
* @param msgId message number available
* @param size size of the message - why it's a long and not an int is a mystery
......@@ -26,6 +40,9 @@ public interface I2PSessionListener {
/** Instruct the client that the session specified seems to be under attack
* and that the client may wish to move its destination to another router.
*
* Unused. Not fully implemented.
*
* @param session session to report abuse to
* @param severity how bad the abuse is
*/
......@@ -39,6 +56,7 @@ public interface I2PSessionListener {
/**
* Notify the client that some error occurred
*
* @param error can be null? or not?
*/
void errorOccurred(I2PSession session, String message, Throwable error);
......
......@@ -20,6 +20,12 @@ public interface I2PSessionMuxedListener extends I2PSessionListener {
* If you register via addSessionListener(),
* this will be called only for the proto(s) and toport(s) you register for.
*
* After this is called, the client should call receiveMessage(msgId).
* There is currently no method for the client to reject the message.
* If the client does not call receiveMessage() within a timeout period
* (currently 30 seconds), the session will delete the message and
* log an error.
*
* @param session session to notify
* @param msgId message number available
* @param size size of the message - why it's a long and not an int is a mystery
......@@ -32,6 +38,15 @@ public interface I2PSessionMuxedListener extends I2PSessionListener {
* Will be called only if you register via addMuxedSessionListener().
* Will be called only for the proto(s) and toport(s) you register for.
*
* After this is called, the client should call receiveMessage(msgId).
* There is currently no method for the client to reject the message.
* If the client does not call receiveMessage() within a timeout period
* (currently 30 seconds), the session will delete the message and
* log an error.
*
* Only one listener is called for a given message, even if more than one
* have registered. See I2PSessionDemultiplexer for details.
*
* @param session session to notify
* @param msgId message number available
* @param size size of the message - why it's a long and not an int is a mystery
......@@ -43,20 +58,27 @@ public interface I2PSessionMuxedListener extends I2PSessionListener {
/** Instruct the client that the session specified seems to be under attack
* and that the client may wish to move its destination to another router.
* All registered listeners will be called.
*
* Unused. Not fully implemented.
*
* @param session session to report abuse to
* @param severity how bad the abuse is
*/
void reportAbuse(I2PSession session, int severity);
/**
* Notify the client that the session has been terminated
* Notify the client that the session has been terminated.
* All registered listeners will be called.
*
*/
void disconnected(I2PSession session);
/**
* Notify the client that some error occurred
* Notify the client that some error occurred.
* All registered listeners will be called.
*
* @param error can be null? or not?
*/
void errorOccurred(I2PSession session, String message, Throwable error);
}
......@@ -34,6 +34,7 @@ class SetDateMessageHandler extends HandlerImpl {
// we did was get the time from ourselves.
if (!_context.isRouterContext())
Clock.getInstance().setNow(msg.getDate().getTime());
// TODO - save router's version string for future reference
session.dateUpdated();
}
}
......@@ -9,40 +9,81 @@ package net.i2p.data.i2cp;
*
*/
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import net.i2p.data.DataFormatException;
import net.i2p.data.DataHelper;
/**
* Request the other side to send us what they think the current time is
* Request the other side to send us what they think the current time is/
* Only supported from client to router.
*
* Since 0.8.7, optionally include a version string.
*/
public class GetDateMessage extends I2CPMessageImpl {
public final static int MESSAGE_TYPE = 32;
private String _version;
public GetDateMessage() {
super();
}
/**
* @param version the client's version String to be sent to the router; may be null
* @since 0.8.7
*/
public GetDateMessage(String version) {
super();
_version = version;
}
/**
* @return may be null
* @since 0.8.7
*/
public String getVersion() {
return _version;
}
@Override
protected void doReadMessage(InputStream in, int size) throws I2CPMessageException, IOException {
// noop
if (size > 0) {
try {
_version = DataHelper.readString(in);
} catch (DataFormatException dfe) {
throw new I2CPMessageException("Bad version string", dfe);
}
}
}
@Override
protected byte[] doWriteMessage() throws I2CPMessageException, IOException {
byte rv[] = new byte[0];
return rv;
if (_version == null)
return new byte[0];
ByteArrayOutputStream os = new ByteArrayOutputStream(16);
try {
DataHelper.writeString(os, _version);
} catch (DataFormatException dfe) {
throw new I2CPMessageException("Error writing out the message data", dfe);
}
return os.toByteArray();
}
public int getType() {
return MESSAGE_TYPE;
}
/* FIXME missing hashCode() method FIXME */
@Override
public int hashCode() {
return MESSAGE_TYPE ^ DataHelper.hashCode(_version);
}
@Override
public boolean equals(Object object) {
if ((object != null) && (object instanceof GetDateMessage)) {
return true;
return DataHelper.eq(_version, ((GetDateMessage)object)._version);
}
return false;
......@@ -52,6 +93,7 @@ public class GetDateMessage extends I2CPMessageImpl {
public String toString() {
StringBuilder buf = new StringBuilder();
buf.append("[GetDateMessage]");
buf.append("\n\tVersion: ").append(_version);
return buf.toString();
}
}
......@@ -19,18 +19,30 @@ import net.i2p.data.DataHelper;
import net.i2p.util.Clock;
/**
* Tell the other side what time it is
* Tell the other side what time it is.
* Only supported from router to client.
*
* Since 0.8.7, optionally include a version string.
*/
public class SetDateMessage extends I2CPMessageImpl {
public final static int MESSAGE_TYPE = 33;
private Date _date;
private String _version;
public SetDateMessage() {
super();
_date = new Date(Clock.getInstance().now());
}
/**
* @param version the router's version String to be sent to the client; may be null
* @since 0.8.7
*/
public SetDateMessage(String version) {
this();
_version = version;
}
public Date getDate() {
return _date;
}
......@@ -39,10 +51,20 @@ public class SetDateMessage extends I2CPMessageImpl {
_date = date;
}
/**
* @return may be null
* @since 0.8.7
*/
public String getVersion() {
return _version;
}
@Override
protected void doReadMessage(InputStream in, int size) throws I2CPMessageException, IOException {
try {
_date = DataHelper.readDate(in);
if (size > DataHelper.DATE_LENGTH)
_version = DataHelper.readString(in);
} catch (DataFormatException dfe) {
throw new I2CPMessageException("Unable to load the message data", dfe);
}
......@@ -52,9 +74,11 @@ public class SetDateMessage extends I2CPMessageImpl {
protected byte[] doWriteMessage() throws I2CPMessageException, IOException {
if (_date == null)
throw new I2CPMessageException("Unable to write out the message as there is not enough data");
ByteArrayOutputStream os = new ByteArrayOutputStream(64);
ByteArrayOutputStream os = new ByteArrayOutputStream(32);
try {
DataHelper.writeDate(os, _date);
if (_version != null)
DataHelper.writeString(os, _version);
} catch (DataFormatException dfe) {
throw new I2CPMessageException("Error writing out the message data", dfe);
}
......@@ -65,12 +89,16 @@ public class SetDateMessage extends I2CPMessageImpl {
return MESSAGE_TYPE;
}
/* FIXME missing hashCode() method */
@Override
public int hashCode() {
return MESSAGE_TYPE ^ DataHelper.hashCode(_version) ^ DataHelper.hashCode(_date);
}
@Override
public boolean equals(Object object) {
if ((object != null) && (object instanceof SetDateMessage)) {
SetDateMessage msg = (SetDateMessage) object;
return DataHelper.eq(_date, msg.getDate());
return DataHelper.eq(_date, msg._date) && DataHelper.eq(_version, msg._version);
}
return false;
......@@ -81,6 +109,7 @@ public class SetDateMessage extends I2CPMessageImpl {
StringBuilder buf = new StringBuilder();
buf.append("[SetDateMessage");
buf.append("\n\tDate: ").append(_date);
buf.append("\n\tVersion: ").append(_version);
buf.append("]");
return buf.toString();
}
......
2011-05-30 zzz
* I2CP:
- Append I2CP Version information to the Get/Set Date Messages,
so that both the router and client are aware of the other side's version,
and future protocol changes will be easier to implement.
Previously, router version information was not available to the client,
so when router and client were in different JVMs,
old clients would work with new routers
but new clients would not work with old routers.
After this change, we can design future changes so that new clients
will work with old routers.
This is an enhancement to the old protocol version byte sent by the client,
which we have never changed and probably never will.
- Prevent a client from setting the router's clock
- Javadocs
* i2psnark: Restrict swarm size for small torrents
* netDb: Don't refetch expiring router infos if we have enough
2011-05-28 zzz
* i2psnark: Fix bug preventing Robert from connecting to snark (thx sponge)
......
......@@ -18,7 +18,7 @@ public class RouterVersion {
/** deprecated */
public final static String ID = "Monotone";
public final static String VERSION = CoreVersion.VERSION;
public final static long BUILD = 11;
public final static long BUILD = 12;
/** for example "-test" */
public final static String EXTRA = "";
......
......@@ -10,6 +10,7 @@ package net.i2p.router.client;
import java.util.Properties;
import net.i2p.CoreVersion;
import net.i2p.data.Payload;
import net.i2p.data.i2cp.BandwidthLimitsMessage;
import net.i2p.data.i2cp.CreateLeaseSetMessage;
......@@ -120,22 +121,30 @@ class ClientMessageEventListener implements I2CPMessageReader.I2CPMessageEventLi
// Is this is a little drastic for an unknown message type?
_runner.stopRunning();
}
public void disconnected(I2CPMessageReader reader) {
if (_runner.isDead()) return;
_runner.disconnected();
}
private void handleGetDate(I2CPMessageReader reader, GetDateMessage message) {
// sent by clients >= 0.8.7
String clientVersion = message.getVersion();
// TODO - save client's version string for future reference
try {
_runner.doSend(new SetDateMessage());
// only send version if the client can handle it (0.8.7 or greater)
_runner.doSend(new SetDateMessage(clientVersion != null ? CoreVersion.VERSION : null));
} catch (I2CPMessageException ime) {
if (_log.shouldLog(Log.ERROR))
_log.error("Error writing out the setDate message", ime);
}
}
/**
* As of 0.8.7, does nothing. Do not allow a client to set the router's clock.
*/
private void handleSetDate(I2CPMessageReader reader, SetDateMessage message) {
_context.clock().setNow(message.getDate().getTime());
//_context.clock().setNow(message.getDate().getTime());
}
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment