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

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

bw limits msg

parent f2bfa2e1
No related branches found
No related tags found
No related merge requests found
package net.i2p.client;
/*
* Released into the public domain
* with no warranty of any kind, either expressed or implied.
*/
import net.i2p.I2PAppContext;
import net.i2p.data.i2cp.I2CPMessage;
import net.i2p.data.i2cp.BandwidthLimitsMessage;
/**
* Handle I2CP BW replies from the router
*/
class BWLimitsMessageHandler extends HandlerImpl {
public BWLimitsMessageHandler(I2PAppContext ctx) {
super(ctx, BandwidthLimitsMessage.MESSAGE_TYPE);
}
public void handleMessage(I2CPMessage message, I2PSessionImpl session) {
_log.debug("Handle message " + message);
BandwidthLimitsMessage msg = (BandwidthLimitsMessage) message;
((I2PSimpleSession)session).bwReceived(msg.getLimits());
}
}
...@@ -17,25 +17,32 @@ import net.i2p.I2PAppContext; ...@@ -17,25 +17,32 @@ import net.i2p.I2PAppContext;
import net.i2p.data.DataHelper; import net.i2p.data.DataHelper;
import net.i2p.data.Destination; import net.i2p.data.Destination;
import net.i2p.data.Hash; import net.i2p.data.Hash;
import net.i2p.data.i2cp.BandwidthLimitsMessage;
import net.i2p.data.i2cp.DestLookupMessage; import net.i2p.data.i2cp.DestLookupMessage;
import net.i2p.data.i2cp.DestReplyMessage; import net.i2p.data.i2cp.DestReplyMessage;
import net.i2p.data.i2cp.GetBandwidthLimitsMessage;
import net.i2p.data.i2cp.I2CPMessageReader; import net.i2p.data.i2cp.I2CPMessageReader;
import net.i2p.util.I2PThread; import net.i2p.util.I2PThread;
import net.i2p.util.Log; import net.i2p.util.Log;
/** /**
* Create a new session for doing naming queries only. Do not create a Destination. * Create a new session for doing naming and bandwidth queries only. Do not create a Destination.
* Don't create a producer. Do not send/receive messages to other Destinations. * Don't create a producer. Do not send/receive messages to other Destinations.
* Cannot handle multiple simultaneous queries atm. * Cannot handle multiple simultaneous queries atm.
* Could be expanded to ask the router other things. * Could be expanded to ask the router other things.
*
* @author zzz
*/ */
class I2PSimpleSession extends I2PSessionImpl2 { class I2PSimpleSession extends I2PSessionImpl2 {
private boolean _destReceived; private boolean _destReceived;
private Object _destReceivedLock; private Object _destReceivedLock;
private Destination _destination; private Destination _destination;
private boolean _bwReceived;
private Object _bwReceivedLock;
private int[] _bwLimits;
/** /**
* Create a new session for doing naming queries only. Do not create a destination. * Create a new session for doing naming and bandwidth queries only. Do not create a destination.
* *
* @throws I2PSessionException if there is a problem * @throws I2PSessionException if there is a problem
*/ */
...@@ -94,6 +101,14 @@ class I2PSimpleSession extends I2PSessionImpl2 { ...@@ -94,6 +101,14 @@ class I2PSimpleSession extends I2PSessionImpl2 {
} }
} }
void bwReceived(int[] i) {
_bwReceived = true;
_bwLimits = i;
synchronized (_bwReceivedLock) {
_bwReceivedLock.notifyAll();
}
}
public Destination lookupDest(Hash h) throws I2PSessionException { public Destination lookupDest(Hash h) throws I2PSessionException {
if (_closed) if (_closed)
return null; return null;
...@@ -110,14 +125,31 @@ class I2PSimpleSession extends I2PSessionImpl2 { ...@@ -110,14 +125,31 @@ class I2PSimpleSession extends I2PSessionImpl2 {
return _destination; return _destination;
} }
public int[] bandwidthLimits() throws I2PSessionException {
if (_closed)
return null;
_bwReceivedLock = new Object();
sendMessage(new GetBandwidthLimitsMessage());
for (int i = 0; i < 5 && !_destReceived; i++) {
try {
synchronized (_bwReceivedLock) {
_bwReceivedLock.wait(1000);
}
} catch (InterruptedException ie) {}
}
_bwReceived = false;
return _bwLimits;
}
/** /**
* Only map message handlers that we will use * Only map message handlers that we will use
*/ */
class SimpleMessageHandlerMap extends I2PClientMessageHandlerMap { class SimpleMessageHandlerMap extends I2PClientMessageHandlerMap {
public SimpleMessageHandlerMap(I2PAppContext context) { public SimpleMessageHandlerMap(I2PAppContext context) {
int highest = DestReplyMessage.MESSAGE_TYPE; int highest = Math.max(DestReplyMessage.MESSAGE_TYPE, BandwidthLimitsMessage.MESSAGE_TYPE);
_handlers = new I2CPMessageHandler[highest+1]; _handlers = new I2CPMessageHandler[highest+1];
_handlers[DestReplyMessage.MESSAGE_TYPE] = new DestReplyMessageHandler(context); _handlers[DestReplyMessage.MESSAGE_TYPE] = new DestReplyMessageHandler(context);
_handlers[BandwidthLimitsMessage.MESSAGE_TYPE] = new BWLimitsMessageHandler(context);
} }
} }
} }
package net.i2p.data.i2cp;
/*
* public domain
*
*/
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import net.i2p.data.DataFormatException;
import net.i2p.data.DataHelper;
import net.i2p.util.Log;
/**
* Tell the other side the limits
*
* @author zzz
*/
public class BandwidthLimitsMessage extends I2CPMessageImpl {
private final static Log _log = new Log(BandwidthLimitsMessage.class);
public final static int MESSAGE_TYPE = 23;
private static final int LIMITS = 16;
private int[] data;
public BandwidthLimitsMessage() {
super();
data = new int[LIMITS];
}
/**
* Let's define it this way.
* Leave some extra. This is only local and rarely sent so we don't care about waste.
*
* 0) Client inbound limit (KBps)
* 1) Client outbound limit (KBps)
* 2) Router inbound limit (KBps)
* 3) Router inbound burst limit (KBps)
* 4) Router outbound limit (KBps)
* 5) Router outbound burst limit (KBps)
* 6) Router burst time (seconds)
* 7-15) undefined
*/
public BandwidthLimitsMessage(int in, int out) {
this();
data[0] = in;
data[1] = out;
}
public int[] getLimits() {
return data;
}
@Override
protected void doReadMessage(InputStream in, int size) throws I2CPMessageException, IOException {
try {
for (int i = 0; i < LIMITS; i++) {
data[i] = (int) DataHelper.readLong(in, 4);
}
} catch (DataFormatException dfe) {
throw new I2CPMessageException("Unable to load the message data", dfe);
}
}
@Override
protected byte[] doWriteMessage() throws I2CPMessageException, IOException {
ByteArrayOutputStream os = new ByteArrayOutputStream(64);
try {
for (int i = 0; i < LIMITS; i++) {
DataHelper.writeLong(os, 4, data[i]);
}
} catch (DataFormatException dfe) {
throw new I2CPMessageException("Error writing out the message data", dfe);
}
return os.toByteArray();
}
public int getType() {
return MESSAGE_TYPE;
}
@Override
public boolean equals(Object object) {
if ((object != null) && (object instanceof BandwidthLimitsMessage)) {
BandwidthLimitsMessage msg = (BandwidthLimitsMessage) object;
return DataHelper.eq(data, msg.getLimits());
}
return false;
}
@Override
public String toString() {
StringBuffer buf = new StringBuffer();
buf.append("[BandwidthLimitsMessage");
buf.append("\n\tIn: ").append(data[0]);
buf.append("\n\tOut: ").append(data[1]);
buf.append("]");
return buf.toString();
}
}
package net.i2p.data.i2cp;
/*
* public domain
*
*/
import java.io.IOException;
import java.io.InputStream;
import net.i2p.util.Log;
/**
* Request the router tells us the current bw limits
*
* @author zzz
*/
public class GetBandwidthLimitsMessage extends I2CPMessageImpl {
private final static Log _log = new Log(GetBandwidthLimitsMessage.class);
public final static int MESSAGE_TYPE = 8;
public GetBandwidthLimitsMessage() {
super();
}
@Override
protected void doReadMessage(InputStream in, int size) throws I2CPMessageException, IOException {
// noop
}
@Override
protected byte[] doWriteMessage() throws I2CPMessageException, IOException {
byte rv[] = new byte[0];
return rv;
}
public int getType() {
return MESSAGE_TYPE;
}
@Override
public boolean equals(Object object) {
if ((object != null) && (object instanceof GetBandwidthLimitsMessage)) {
return true;
}
return false;
}
@Override
public String toString() {
StringBuffer buf = new StringBuffer();
buf.append("[GetBandwidthLimitsMessage]");
return buf.toString();
}
}
...@@ -94,6 +94,10 @@ public class I2CPMessageHandler { ...@@ -94,6 +94,10 @@ public class I2CPMessageHandler {
return new DestLookupMessage(); return new DestLookupMessage();
case DestReplyMessage.MESSAGE_TYPE: case DestReplyMessage.MESSAGE_TYPE:
return new DestReplyMessage(); return new DestReplyMessage();
case GetBandwidthLimitsMessage.MESSAGE_TYPE:
return new GetBandwidthLimitsMessage();
case BandwidthLimitsMessage.MESSAGE_TYPE:
return new BandwidthLimitsMessage();
default: default:
throw new I2CPMessageException("The type " + type + " is an unknown I2CP message"); throw new I2CPMessageException("The type " + type + " is an unknown I2CP message");
} }
......
...@@ -11,10 +11,12 @@ package net.i2p.router.client; ...@@ -11,10 +11,12 @@ package net.i2p.router.client;
import java.util.Properties; import java.util.Properties;
import net.i2p.data.Payload; import net.i2p.data.Payload;
import net.i2p.data.i2cp.BandwidthLimitsMessage;
import net.i2p.data.i2cp.CreateLeaseSetMessage; import net.i2p.data.i2cp.CreateLeaseSetMessage;
import net.i2p.data.i2cp.CreateSessionMessage; import net.i2p.data.i2cp.CreateSessionMessage;
import net.i2p.data.i2cp.DestLookupMessage; import net.i2p.data.i2cp.DestLookupMessage;
import net.i2p.data.i2cp.DestroySessionMessage; import net.i2p.data.i2cp.DestroySessionMessage;
import net.i2p.data.i2cp.GetBandwidthLimitsMessage;
import net.i2p.data.i2cp.GetDateMessage; import net.i2p.data.i2cp.GetDateMessage;
import net.i2p.data.i2cp.I2CPMessage; import net.i2p.data.i2cp.I2CPMessage;
import net.i2p.data.i2cp.I2CPMessageException; import net.i2p.data.i2cp.I2CPMessageException;
...@@ -93,6 +95,9 @@ class ClientMessageEventListener implements I2CPMessageReader.I2CPMessageEventLi ...@@ -93,6 +95,9 @@ class ClientMessageEventListener implements I2CPMessageReader.I2CPMessageEventLi
case ReconfigureSessionMessage.MESSAGE_TYPE: case ReconfigureSessionMessage.MESSAGE_TYPE:
handleReconfigureSession(reader, (ReconfigureSessionMessage)message); handleReconfigureSession(reader, (ReconfigureSessionMessage)message);
break; break;
case GetBandwidthLimitsMessage.MESSAGE_TYPE:
handleGetBWLimits(reader, (GetBandwidthLimitsMessage)message);
break;
default: default:
if (_log.shouldLog(Log.ERROR)) if (_log.shouldLog(Log.ERROR))
_log.error("Unhandled I2CP type received: " + message.getType()); _log.error("Unhandled I2CP type received: " + message.getType());
...@@ -274,6 +279,24 @@ class ClientMessageEventListener implements I2CPMessageReader.I2CPMessageEventLi ...@@ -274,6 +279,24 @@ class ClientMessageEventListener implements I2CPMessageReader.I2CPMessageEventLi
} }
} }
/**
* Divide router limit by 2 for overhead.
* This could someday give a different answer to each client.
* But it's not enforced anywhere.
*/
private void handleGetBWLimits(I2CPMessageReader reader, GetBandwidthLimitsMessage message) {
if (_log.shouldLog(Log.INFO))
_log.info("Got BW Limits request");
int in = _context.bandwidthLimiter().getInboundKBytesPerSecond() / 2;
int out = _context.bandwidthLimiter().getOutboundKBytesPerSecond() / 2;
BandwidthLimitsMessage msg = new BandwidthLimitsMessage(in, out);
try {
_runner.doSend(msg);
} catch (I2CPMessageException ime) {
_log.error("Error writing out the session status message", ime);
}
}
// this *should* be mod 65536, but UnsignedInteger is still b0rked. FIXME // this *should* be mod 65536, but UnsignedInteger is still b0rked. FIXME
private final static int MAX_SESSION_ID = 32767; private final static int MAX_SESSION_ID = 32767;
......
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