Search in sources :

Example 16 with DirectByteBuffer

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);
}
Also used : IOException(java.io.IOException) DirectByteBuffer(com.biglybt.core.util.DirectByteBuffer) ByteBuffer(java.nio.ByteBuffer) DirectByteBuffer(com.biglybt.core.util.DirectByteBuffer)

Example 17 with DirectByteBuffer

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();
            }
        }
    }
}
Also used : DirectByteBuffer(com.biglybt.core.util.DirectByteBuffer) DirectByteBuffer(com.biglybt.core.util.DirectByteBuffer) ByteBuffer(java.nio.ByteBuffer)

Example 18 with DirectByteBuffer

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 });
}
Also used : Message(com.biglybt.core.peermanager.messaging.Message) ArrayList(java.util.ArrayList) IOException(java.io.IOException) DirectByteBuffer(com.biglybt.core.util.DirectByteBuffer)

Example 19 with DirectByteBuffer

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();
        }
    }
}
Also used : ArrayList(java.util.ArrayList) DirectByteBuffer(com.biglybt.core.util.DirectByteBuffer)

Example 20 with DirectByteBuffer

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();
        }
    }
}
Also used : ArrayList(java.util.ArrayList) RawMessage(com.biglybt.core.networkmanager.RawMessage) DirectByteBuffer(com.biglybt.core.util.DirectByteBuffer)

Aggregations

DirectByteBuffer (com.biglybt.core.util.DirectByteBuffer)33 ByteBuffer (java.nio.ByteBuffer)8 ArrayList (java.util.ArrayList)8 HashMap (java.util.HashMap)7 Map (java.util.Map)7 RawMessage (com.biglybt.core.networkmanager.RawMessage)6 IOException (java.io.IOException)6 Message (com.biglybt.core.peermanager.messaging.Message)5 RawMessageImpl (com.biglybt.core.networkmanager.impl.RawMessageImpl)3 CacheFileManagerException (com.biglybt.core.diskmanager.cache.CacheFileManagerException)2 DiskManagerPiece (com.biglybt.core.disk.DiskManagerPiece)1 DiskManagerFileInfoImpl (com.biglybt.core.disk.impl.DiskManagerFileInfoImpl)1 DiskManagerRecheckInstance (com.biglybt.core.disk.impl.DiskManagerRecheckInstance)1 DMPieceList (com.biglybt.core.disk.impl.piecemapper.DMPieceList)1 DMPieceMapEntry (com.biglybt.core.disk.impl.piecemapper.DMPieceMapEntry)1 CacheFile (com.biglybt.core.diskmanager.cache.CacheFile)1 LogEvent (com.biglybt.core.logging.LogEvent)1 MessageException (com.biglybt.core.peermanager.messaging.MessageException)1 AESemaphore (com.biglybt.core.util.AESemaphore)1 ByteArrayHashMap (com.biglybt.core.util.ByteArrayHashMap)1