use of com.biglybt.core.util.DirectByteBuffer in project BiglyBT by BiglySoftware.
the class TransportHelperFilterStream method write.
@Override
public long write(ByteBuffer[] buffers, int array_offset, int length) throws IOException {
if (write_buffer_pending_byte != null) {
if (transport.write(write_buffer_pending_byte, false) == 0) {
return (0);
}
write_buffer_pending_byte = null;
}
long total_written = 0;
if (write_buffer_pending_db != null) {
ByteBuffer write_buffer_pending = write_buffer_pending_db.getBuffer(DirectByteBuffer.SS_NET);
int max_writable = 0;
for (int i = array_offset; i < array_offset + length; i++) {
ByteBuffer source_buffer = buffers[i];
int position = source_buffer.position();
int limit = source_buffer.limit();
int size = limit - position;
max_writable += size;
}
int pending_position = write_buffer_pending.position();
int pending_limit = write_buffer_pending.limit();
int pending_writable = pending_limit - pending_position;
if (pending_writable > max_writable) {
pending_writable = max_writable;
write_buffer_pending.limit(pending_position + pending_writable);
}
int written = transport.write(write_buffer_pending, false);
write_buffer_pending.limit(pending_limit);
if (written > 0) {
total_written = written;
if (write_buffer_pending.remaining() == 0) {
write_buffer_pending_db.returnToPool();
write_buffer_pending_db = null;
}
// skip "written" bytes in the source
int skip = written;
for (int i = array_offset; i < array_offset + length; i++) {
ByteBuffer source_buffer = buffers[i];
int position = source_buffer.position();
int limit = source_buffer.limit();
int size = limit - position;
if (size <= skip) {
source_buffer.position(limit);
skip -= size;
} else {
source_buffer.position(position + skip);
skip = 0;
break;
}
}
if (skip != 0) {
throw (new IOException("skip inconsistent - " + skip));
}
}
if (total_written < pending_writable || total_written == max_writable) {
return (total_written);
}
}
for (int i = array_offset; i < array_offset + length; i++) {
ByteBuffer source_buffer = buffers[i];
int position = source_buffer.position();
int limit = source_buffer.limit();
int size = limit - position;
if (size == 0) {
continue;
}
DirectByteBuffer target_buffer_db = DirectByteBufferPool.getBuffer(DirectByteBuffer.AL_NET_CRYPT, size);
try {
ByteBuffer target_buffer = target_buffer_db.getBuffer(DirectByteBuffer.SS_NET);
cryptoOut(source_buffer, target_buffer);
target_buffer.position(0);
boolean partial_write = false;
for (int j = i + 1; j < array_offset + length; j++) {
if (buffers[j].hasRemaining()) {
partial_write = true;
}
}
int written = transport.write(target_buffer, partial_write);
total_written += written;
source_buffer.position(position + written);
if (written < size) {
write_buffer_pending_db = target_buffer_db;
target_buffer_db = null;
if (written == 0) {
// we gotta pretend at least 1 byte was written to
// guarantee that the caller writes the rest
write_buffer_pending_byte = ByteBuffer.wrap(new byte[] { target_buffer.get() });
source_buffer.get();
total_written++;
}
break;
}
} finally {
if (target_buffer_db != null) {
target_buffer_db.returnToPool();
}
}
}
return (total_written);
}
use of com.biglybt.core.util.DirectByteBuffer in project BiglyBT by BiglySoftware.
the class TransportHelperFilterStream method read.
@Override
public long read(ByteBuffer[] buffers, int array_offset, int length) throws IOException {
int total_read = 0;
DirectByteBuffer[] copy_db = new DirectByteBuffer[buffers.length];
ByteBuffer[] copy = new ByteBuffer[buffers.length];
try {
for (int i = array_offset; i < array_offset + length; i++) {
ByteBuffer buffer = buffers[i];
int size = buffer.remaining();
if (size > 0) {
copy_db[i] = DirectByteBufferPool.getBuffer(DirectByteBuffer.AL_NET_CRYPT, size);
copy[i] = copy_db[i].getBuffer(DirectByteBuffer.SS_NET);
} else {
copy[i] = ByteBuffer.allocate(0);
}
}
total_read += transport.read(copy, array_offset, length);
for (int i = array_offset; i < array_offset + length; i++) {
ByteBuffer source_buffer = copy[i];
if (source_buffer != null) {
ByteBuffer target_buffer = buffers[i];
int source_position = source_buffer.position();
if (source_position > 0) {
source_buffer.flip();
cryptoIn(source_buffer, target_buffer);
}
}
}
return (total_read);
} finally {
for (int i = 0; i < copy_db.length; i++) {
if (copy_db[i] != null) {
copy_db[i].returnToPool();
}
}
}
}
use of com.biglybt.core.util.DirectByteBuffer in project BiglyBT by BiglySoftware.
the class IncomingMessageQueueImpl method receiveFromTransport.
/**
* Receive (read) message(s) data from the underlying transport.
* @param max_bytes to read
* @return number of bytes received
* @throws IOException on receive error
*/
@Override
public int[] receiveFromTransport(int max_bytes, boolean protocol_is_free) throws IOException {
if (max_bytes < 1) {
if (!protocol_is_free) {
Debug.out("max_bytes < 1: " + max_bytes);
}
return new int[2];
}
if (listeners.isEmpty()) {
Debug.out("no queue listeners registered!");
throw new IOException("no queue listeners registered!");
}
int bytes_read;
try {
// perform decode op
bytes_read = stream_decoder.performStreamDecode(connection.getTransport(), max_bytes);
} catch (RuntimeException e) {
Debug.out("Stream decode for " + connection.getString() + " failed: " + Debug.getNestedExceptionMessageAndStack(e));
throw (e);
}
// check if anything was decoded and notify listeners if so
Message[] messages = stream_decoder.removeDecodedMessages();
if (messages != null) {
for (int i = 0; i < messages.length; i++) {
Message msg = messages[i];
if (msg == null) {
System.out.println("received msg == null [messages.length=" + messages.length + ", #" + i + "]: " + connection.getTransport().getDescription());
continue;
}
// copy-on-write
ArrayList listeners_ref = listeners;
boolean handled = false;
for (int x = 0; x < listeners_ref.size(); x++) {
MessageQueueListener mql = (MessageQueueListener) listeners_ref.get(x);
if (mql.messageReceived(msg)) {
handled = true;
}
}
if (!handled) {
if (listeners_ref.size() > 0) {
System.out.println("no registered listeners [out of " + listeners_ref.size() + "] handled decoded message [" + msg.getDescription() + "]");
}
DirectByteBuffer[] buffs = msg.getData();
for (int x = 0; x < buffs.length; x++) {
buffs[x].returnToPool();
}
}
}
}
int protocol_read = stream_decoder.getProtocolBytesDecoded();
if (protocol_read > 0) {
// copy-on-write
ArrayList listeners_ref = listeners;
for (int i = 0; i < listeners_ref.size(); i++) {
MessageQueueListener mql = (MessageQueueListener) listeners_ref.get(i);
mql.protocolBytesReceived(protocol_read);
}
}
int data_read = stream_decoder.getDataBytesDecoded();
if (data_read > 0) {
// copy-on-write
ArrayList listeners_ref = listeners;
for (int i = 0; i < listeners_ref.size(); i++) {
MessageQueueListener mql = (MessageQueueListener) listeners_ref.get(i);
mql.dataBytesReceived(data_read);
}
}
// ideally bytes_read = data_read + protocol_read. in case it isn't then we want to
// return bytes_read = d + p with bias to p
data_read = bytes_read - protocol_read;
if (data_read < 0) {
protocol_read = bytes_read;
data_read = 0;
}
return (new int[] { data_read, protocol_read });
}
use of com.biglybt.core.util.DirectByteBuffer in project BiglyBT by BiglySoftware.
the class IncomingMessageQueueImpl method notifyOfExternallyReceivedMessage.
/**
* Notifty the queue (and its listeners) of a message received externally on the queue's behalf.
* @param message received externally
*/
@Override
public void notifyOfExternallyReceivedMessage(Message message) throws IOException {
// copy-on-write
ArrayList listeners_ref = listeners;
boolean handled = false;
DirectByteBuffer[] dbbs = message.getData();
int size = 0;
for (int i = 0; i < dbbs.length; i++) {
size += dbbs[i].remaining(DirectByteBuffer.SS_NET);
}
for (int x = 0; x < listeners_ref.size(); x++) {
MessageQueueListener mql = (MessageQueueListener) listeners_ref.get(x);
if (mql.messageReceived(message)) {
handled = true;
}
if (message.getType() == Message.TYPE_DATA_PAYLOAD) {
mql.dataBytesReceived(size);
} else {
mql.protocolBytesReceived(size);
}
}
if (!handled) {
if (listeners_ref.size() > 0) {
System.out.println("no registered listeners [out of " + listeners_ref.size() + "] handled decoded message [" + message.getDescription() + "]");
}
DirectByteBuffer[] buffs = message.getData();
for (int x = 0; x < buffs.length; x++) {
buffs[x].returnToPool();
}
}
}
use of com.biglybt.core.util.DirectByteBuffer in project BiglyBT by BiglySoftware.
the class OutgoingMessageQueueImpl method removeMessagesOfType.
/**
* Remove all messages of the given types from the queue.
* NOTE: Allows for manual listener notification at some later time,
* using doListenerNotifications(), instead of notifying immediately
* from within this method. This is useful if you want to invoke
* listeners outside of some greater synchronised block to avoid
* deadlock.
* @param message_types type to remove
* @param manual_listener_notify true for manual notification, false for automatic
*/
@Override
public void removeMessagesOfType(Message[] message_types, boolean manual_listener_notify) {
if (message_types == null)
return;
ArrayList<RawMessage> messages_removed = null;
try {
queue_mon.enter();
for (Iterator<RawMessage> i = queue.iterator(); i.hasNext(); ) {
RawMessage msg = i.next();
for (int t = 0; t < message_types.length; t++) {
boolean same_type = message_types[t].getID().equals(msg.getID());
if (same_type && msg.getRawData()[0].position(DirectByteBuffer.SS_NET) == 0) {
// dont remove a half-sent message
if (msg == urgent_message)
urgent_message = null;
DirectByteBuffer[] payload = msg.getRawData();
int remaining = 0;
for (int x = 0; x < payload.length; x++) {
remaining += payload[x].remaining(DirectByteBuffer.SS_NET);
}
total_size -= remaining;
if (msg.getType() == Message.TYPE_DATA_PAYLOAD) {
total_data_size -= remaining;
}
if (manual_listener_notify) {
NotificationItem item = new NotificationItem(NotificationItem.MESSAGE_REMOVED);
item.message = msg;
try {
delayed_notifications_mon.enter();
delayed_notifications.add(item);
} finally {
delayed_notifications_mon.exit();
}
} else {
if (messages_removed == null) {
messages_removed = new ArrayList<>();
}
messages_removed.add(msg);
}
i.remove();
break;
}
}
}
if (queue.isEmpty()) {
percent_complete = -1;
}
} finally {
queue_mon.exit();
}
if (!manual_listener_notify && messages_removed != null) {
// do listener notifications now
ArrayList listeners_ref = listeners;
for (int x = 0; x < messages_removed.size(); x++) {
RawMessage msg = messages_removed.get(x);
for (int i = 0; i < listeners_ref.size(); i++) {
MessageQueueListener listener = (MessageQueueListener) listeners_ref.get(i);
listener.messageRemoved(msg.getBaseMessage());
}
msg.destroy();
}
}
}
Aggregations