use of com.biglybt.core.networkmanager.RawMessage in project BiglyBT by BiglySoftware.
the class OutgoingMessageQueueImpl method addMessage.
/**
* Add a message to the message 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 message to add
* @param manual_listener_notify true for manual notification, false for automatic
*/
@Override
public void addMessage(Message message, boolean manual_listener_notify) {
// do message add notifications
boolean allowed = true;
ArrayList list_ref = listeners;
for (int i = 0; i < list_ref.size(); i++) {
MessageQueueListener listener = (MessageQueueListener) list_ref.get(i);
allowed = allowed && listener.messageAdded(message);
}
if (!allowed) {
// message.destroy(); //TODO destroy????
return;
}
RawMessage[] rmesgs = stream_encoder.encodeMessage(message);
if (destroyed) {
// queue is shutdown, drop any added messages
for (int i = 0; i < rmesgs.length; i++) {
rmesgs[i].destroy();
}
return;
}
for (int i = 0; i < rmesgs.length; i++) {
RawMessage rmesg = rmesgs[i];
removeMessagesOfType(rmesg.messagesToRemove(), manual_listener_notify);
try {
queue_mon.enter();
int pos = 0;
for (Iterator<RawMessage> it = queue.iterator(); it.hasNext(); ) {
RawMessage msg = it.next();
if (rmesg.getPriority() > msg.getPriority() && msg.getRawData()[0].position(DirectByteBuffer.SS_NET) == 0) {
// but don't insert in front of a half-sent message
break;
}
pos++;
}
if (rmesg.isNoDelay()) {
urgent_message = rmesg;
}
queue.add(pos, rmesg);
DirectByteBuffer[] payload = rmesg.getRawData();
int remaining = 0;
for (int j = 0; j < payload.length; j++) {
remaining += payload[j].remaining(DirectByteBuffer.SS_NET);
}
total_size += remaining;
if (rmesg.getType() == Message.TYPE_DATA_PAYLOAD) {
total_data_size += remaining;
}
} finally {
queue_mon.exit();
}
if (manual_listener_notify) {
// register listener event for later, manual notification
NotificationItem item = new NotificationItem(NotificationItem.MESSAGE_ADDED);
item.message = rmesg;
try {
delayed_notifications_mon.enter();
delayed_notifications.add(item);
} finally {
delayed_notifications_mon.exit();
}
} else {
// do listener notification now
ArrayList listeners_ref = listeners;
for (int j = 0; j < listeners_ref.size(); j++) {
MessageQueueListener listener = (MessageQueueListener) listeners_ref.get(j);
listener.messageQueued(rmesg.getBaseMessage());
}
}
}
}
use of com.biglybt.core.networkmanager.RawMessage in project BiglyBT by BiglySoftware.
the class HTTPMessageEncoder method encodeMessage.
@Override
public RawMessage[] encodeMessage(Message message) {
String id = message.getID();
// System.out.println( "encodeMessage: " + message.getID());
RawMessage raw_message = null;
if (id.equals(BTMessage.ID_BT_HANDSHAKE)) {
raw_message = http_connection.encodeHandShake(message);
} else if (id.equals(BTMessage.ID_BT_CHOKE)) {
raw_message = http_connection.encodeChoke();
} else if (id.equals(BTMessage.ID_BT_UNCHOKE)) {
raw_message = http_connection.encodeUnchoke();
} else if (id.equals(BTMessage.ID_BT_BITFIELD)) {
raw_message = http_connection.encodeBitField();
} else if (id.equals(BTMessage.ID_BT_PIECE)) {
return (http_connection.encodePiece(message));
} else if (id.equals(HTTPMessage.MSG_ID)) {
raw_message = ((HTTPMessage) message).encode(message);
}
if (raw_message == null) {
raw_message = http_connection.getEmptyRawMessage(message);
}
return (new RawMessage[] { raw_message });
}
use of com.biglybt.core.networkmanager.RawMessage in project BiglyBT by BiglySoftware.
the class BTMessageFactory method createBTRawMessage.
/**
* Create the proper BT raw message from the given base message.
* @param base_message to create from
* @return BT raw message
*/
public static RawMessage createBTRawMessage(Message base_message) {
if (base_message instanceof RawMessage) {
// used for handshake and keep-alive messages
return (RawMessage) base_message;
}
LegacyData ld = (LegacyData) legacy_data.get(base_message.getID());
if (ld == null) {
Debug.out("legacy message type id not found for [" + base_message.getID() + "]");
// message id type not found
return null;
}
DirectByteBuffer[] payload = base_message.getData();
int payload_size = 0;
for (int i = 0; i < payload.length; i++) {
payload_size += payload[i].remaining(DirectByteBuffer.SS_MSG);
}
DirectByteBuffer header = DirectByteBufferPool.getBuffer(DirectByteBuffer.AL_MSG_BT_HEADER, 5);
header.putInt(DirectByteBuffer.SS_MSG, 1 + payload_size);
header.put(DirectByteBuffer.SS_MSG, ld.bt_id);
header.flip(DirectByteBuffer.SS_MSG);
DirectByteBuffer[] raw_buffs = new DirectByteBuffer[payload.length + 1];
raw_buffs[0] = header;
System.arraycopy(payload, 0, raw_buffs, 1, payload.length);
return new RawMessageImpl(base_message, raw_buffs, ld.priority, ld.is_no_delay, ld.to_remove);
}
use of com.biglybt.core.networkmanager.RawMessage in project BiglyBT by BiglySoftware.
the class GenericMessageEncoder method encodeMessage.
@Override
public RawMessage[] encodeMessage(Message _message) {
GenericMessage message = (GenericMessage) _message;
DirectByteBuffer payload = message.getPayload();
if (message.isAlreadyEncoded()) {
return (new RawMessage[] { new RawMessageImpl(message, new DirectByteBuffer[] { payload }, RawMessage.PRIORITY_NORMAL, // send immediately
true, new Message[0]) });
} else {
DirectByteBuffer header = DirectByteBufferPool.getBuffer(DirectByteBuffer.AL_EXTERNAL, 4);
header.putInt(DirectByteBuffer.SS_MSG, payload.remaining(DirectByteBuffer.SS_MSG));
header.flip(DirectByteBuffer.SS_MSG);
return (new RawMessage[] { new RawMessageImpl(message, new DirectByteBuffer[] { header, payload }, RawMessage.PRIORITY_NORMAL, // send immediately
true, new Message[0]) });
}
}
use of com.biglybt.core.networkmanager.RawMessage in project BiglyBT by BiglySoftware.
the class HTTPNetworkConnection method encodePiece.
protected RawMessage[] encodePiece(Message message) {
last_http_activity_time = SystemTime.getCurrentTime();
BTPiece piece = (BTPiece) message;
List<pendingRequest> ready_requests = new ArrayList<>();
boolean found = false;
synchronized (outstanding_requests) {
if (destroyed) {
return (new RawMessage[] { getEmptyRawMessage(message) });
}
for (int i = 0; i < outstanding_requests.size(); i++) {
pendingRequest req = outstanding_requests.get(i);
if (req.getPieceNumber() == piece.getPieceNumber() && req.getStart() == piece.getPieceOffset() && req.getLength() == piece.getPieceData().remaining(DirectByteBuffer.SS_NET)) {
if (req.getBTPiece() == null) {
req.setBTPiece(piece);
found = true;
if (i == 0) {
Iterator<pendingRequest> it = outstanding_requests.iterator();
while (it.hasNext()) {
pendingRequest r = it.next();
BTPiece btp = r.getBTPiece();
if (btp == null) {
break;
}
it.remove();
ready_requests.add(r);
}
}
break;
}
}
}
}
if (!found) {
Debug.out("request not matched");
return (new RawMessage[] { getEmptyRawMessage(message) });
}
if (ready_requests.size() == 0) {
return (new RawMessage[] { getEmptyRawMessage(message) });
}
try {
submitBTRequests();
} catch (IOException e) {
}
pendingRequest req = (pendingRequest) ready_requests.get(0);
DirectByteBuffer[] buffers;
httpRequest http_request = req.getHTTPRequest();
RawMessage[] raw_messages = new RawMessage[ready_requests.size()];
for (int i = 0; i < raw_messages.length; i++) {
buffers = new DirectByteBuffer[2];
if (!http_request.hasSentFirstReply()) {
http_request.setSentFirstReply();
String header = encodeHeader(http_request);
buffers[0] = new DirectByteBuffer(ByteBuffer.wrap(header.getBytes()));
} else {
// we have to do this as core code assumes buffer entry 0 is protocol
buffers[0] = new DirectByteBuffer(ByteBuffer.allocate(0));
}
req = (pendingRequest) ready_requests.get(i);
BTPiece this_piece = req.getBTPiece();
int piece_number = this_piece.getPieceNumber();
if (!piece_map.get(piece_number)) {
// kinda crappy as it triggers on first block of piece, however better
// than nothing
piece_map.set(piece_number);
decoder.addMessage(new BTHave(piece_number, (byte) 1));
}
buffers[1] = this_piece.getPieceData();
req.logQueued();
if (request_listeners != null) {
Iterator<requestListener> it = request_listeners.iterator();
while (it.hasNext()) {
((requestListener) it.next()).requestComplete(req);
}
}
raw_messages[i] = new RawMessageImpl(this_piece, buffers, RawMessage.PRIORITY_HIGH, true, new Message[0]);
}
return (raw_messages);
}
Aggregations