bw limits msg
This commit is contained in:
25
core/java/src/net/i2p/client/BWLimitsMessageHandler.java
Normal file
25
core/java/src/net/i2p/client/BWLimitsMessageHandler.java
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
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;
|
|||||||
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 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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 {
|
|||||||
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
101
core/java/src/net/i2p/data/i2cp/BandwidthLimitsMessage.java
Normal file
101
core/java/src/net/i2p/data/i2cp/BandwidthLimitsMessage.java
Normal file
@ -0,0 +1,101 @@
|
|||||||
|
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();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,56 @@
|
|||||||
|
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 {
|
|||||||
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;
|
|||||||
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
|
|||||||
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
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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;
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user