From 2254995ee3f90ee9042be6d1e2f0504db74841ad Mon Sep 17 00:00:00 2001 From: Danny van Heumen Date: Tue, 23 Sep 2014 23:23:50 +0200 Subject: [PATCH] Defined and implemented Operation Set Basic Instant Messaging Transport for querying protocol implementation for operational boundaries. * Defined the Operation Set for querying transport operation. * Also implemented the Operation Set in IRC protocol support. * OTR plugin has been modified to take advantage of the newly defined Operation Set and queries the protocol for input on building fragmentation instructions. In case the protocol does not implement the Operation Set, then it will fall back to OTR defaults. --- .../impl/protocol/irc/IrcStack.java | 20 +++++++ ...rationSetBasicInstantMessagingIrcImpl.java | 34 ++++++++++- .../irc/ProtocolProviderServiceIrcImpl.java | 5 ++ .../plugin/otr/ScOtrEngineImpl.java | 57 +++++++++++-------- .../communicator/plugin/otr/otr.manifest.mf | 3 +- ...tionSetBasicInstantMessagingTransport.java | 51 +++++++++++++++++ 6 files changed, 141 insertions(+), 29 deletions(-) create mode 100644 src/net/java/sip/communicator/service/protocol/OperationSetBasicInstantMessagingTransport.java diff --git a/src/net/java/sip/communicator/impl/protocol/irc/IrcStack.java b/src/net/java/sip/communicator/impl/protocol/irc/IrcStack.java index 22aab66c8..231f8a98b 100644 --- a/src/net/java/sip/communicator/impl/protocol/irc/IrcStack.java +++ b/src/net/java/sip/communicator/impl/protocol/irc/IrcStack.java @@ -59,6 +59,12 @@ public class IrcStack * */ + /** + * Maximum message size for IRC messages given the spec specifies a buffer + * of 512 bytes. The command ending (CRLF) takes up 2 bytes. + */ + private static final int IRC_PROTOCOL_MAXIMUM_MESSAGE_SIZE = 510; + /** * Clean-up delay. The clean up task clears any remaining chat room list * cache. Since there's no pointing in timing it exactly, delay the clean up @@ -1186,6 +1192,20 @@ private static ChatRoomMemberRole convertMemberMode(final char modeSymbol) return Mode.bySymbol(modeSymbol).getRole(); } + /** + * Calculate maximum message size that can be transmitted. + * + * @param contact receiving contact + * @return returns maximum message size + */ + public int calculateMaximumMessageSize(final Contact contact) + { + final String identity = getIdentityString(); + return IRC_PROTOCOL_MAXIMUM_MESSAGE_SIZE + - (":" + identity + " PRIVMSG " + contact.getAddress() + " :") + .length(); + } + /** * A listener for server-level messages (any messages that are related to * the server, the connection, that are not related to any chatroom in diff --git a/src/net/java/sip/communicator/impl/protocol/irc/OperationSetBasicInstantMessagingIrcImpl.java b/src/net/java/sip/communicator/impl/protocol/irc/OperationSetBasicInstantMessagingIrcImpl.java index 613026327..07e4308e1 100644 --- a/src/net/java/sip/communicator/impl/protocol/irc/OperationSetBasicInstantMessagingIrcImpl.java +++ b/src/net/java/sip/communicator/impl/protocol/irc/OperationSetBasicInstantMessagingIrcImpl.java @@ -1,6 +1,6 @@ /* * Jitsi, the OpenSource Java VoIP and Instant Messaging client. - * + * * Distributable under LGPL license. See terms of license at gnu.org. */ package net.java.sip.communicator.impl.protocol.irc; @@ -17,11 +17,13 @@ */ public class OperationSetBasicInstantMessagingIrcImpl extends AbstractOperationSetBasicInstantMessaging + implements OperationSetBasicInstantMessagingTransport { /** * Logger. */ - private static final Logger LOGGER = Logger.getLogger(OperationSetBasicInstantMessagingIrcImpl.class); + private static final Logger LOGGER = Logger + .getLogger(OperationSetBasicInstantMessagingIrcImpl.class); /** * IRC protocol provider service. @@ -171,7 +173,8 @@ public boolean isContentTypeSupported(final String contentType) * @param from the sender */ @Override - protected void fireMessageReceived(final Message message, final Contact from) + protected void fireMessageReceived(final Message message, + final Contact from) { super.fireMessageReceived(message, from); } @@ -201,4 +204,29 @@ protected void fireMessageDeliveryFailed(final Message message, { super.fireMessageDeliveryFailed(message, to, errorCode); } + + /** + * Calculate the maximum message size for IRC messages. + * + * @param contact the contact receiving the message + * @return returns the size the message can be at maximum to receive a + * complete message. + */ + @Override + public int maximumMessageSize(final Contact contact) + { + return this.provider.getIrcStack().calculateMaximumMessageSize(contact); + } + + /** + * Calculate number of messages allowed to send over IRC. + * + * @param contact contact receiving the messages + * @return returns number of messages that can be received at maximum + */ + @Override + public int numberOfMessages(final Contact contact) + { + return OperationSetBasicInstantMessagingTransport.UNLIMITED; + } } diff --git a/src/net/java/sip/communicator/impl/protocol/irc/ProtocolProviderServiceIrcImpl.java b/src/net/java/sip/communicator/impl/protocol/irc/ProtocolProviderServiceIrcImpl.java index e8a37417a..bd6cf841b 100644 --- a/src/net/java/sip/communicator/impl/protocol/irc/ProtocolProviderServiceIrcImpl.java +++ b/src/net/java/sip/communicator/impl/protocol/irc/ProtocolProviderServiceIrcImpl.java @@ -122,8 +122,13 @@ protected void initialize(final String userID, final AccountID accountID) this.instantMessaging = new OperationSetBasicInstantMessagingIrcImpl(this); + // Register basic instant messaging support. addSupportedOperationSet(OperationSetBasicInstantMessaging.class, this.instantMessaging); + // Register basic instant messaging transport support. + addSupportedOperationSet( + OperationSetBasicInstantMessagingTransport.class, + this.instantMessaging); //Initialize persistent presence persistentPresence = diff --git a/src/net/java/sip/communicator/plugin/otr/ScOtrEngineImpl.java b/src/net/java/sip/communicator/plugin/otr/ScOtrEngineImpl.java index f14c2ec7f..b7e184a53 100644 --- a/src/net/java/sip/communicator/plugin/otr/ScOtrEngineImpl.java +++ b/src/net/java/sip/communicator/plugin/otr/ScOtrEngineImpl.java @@ -14,7 +14,6 @@ import net.java.otr4j.*; import net.java.otr4j.crypto.*; import net.java.otr4j.session.*; -import net.java.sip.communicator.impl.protocol.irc.*; import net.java.sip.communicator.plugin.otr.OtrContactManager.OtrContact; import net.java.sip.communicator.plugin.otr.authdialog.*; import net.java.sip.communicator.service.browserlauncher.*; @@ -431,33 +430,43 @@ public FragmenterInstructions getFragmenterInstructions( final SessionID sessionID) { final OtrContact otrContact = getOtrContact(sessionID); - // FIXME Change this into querying an Operation Set that provides - // Instant Message medium/transport information that we can use to - // determine fragmentation parameters. - if (ProtocolNames.IRC.equals(otrContact.contact - .getProtocolProvider().getProtocolName())) + final OperationSetBasicInstantMessagingTransport transport = + otrContact.contact.getProtocolProvider().getOperationSet( + OperationSetBasicInstantMessagingTransport.class); + if (transport == null) { - // :!@ PRIVMSG : - // - // Example: - // :ircotrtest!~ircotrtes@77-175-185-165.FTTH.ispfabriek.nl - // PRIVMSG test12345abc : - final String identity = - ((ProtocolProviderServiceIrcImpl) otrContact.contact - .getProtocolProvider()).getIrcStack() - .getIdentityString(); - final int size = - 510 - (":" + identity + " PRIVMSG " - + otrContact.contact.getAddress() + " :").length(); - return new FragmenterInstructions( - FragmenterInstructions.UNLIMITED, size); + // There is no operation set for querying transport parameters. + // Assuming transport capabilities are unlimited. + if (logger.isDebugEnabled()) + { + logger.debug("No implementation of " + + "BasicInstantMessagingTransport available. Assuming " + + "OTR defaults for OTR fragmentation instructions."); + } + return null; } - else + int messageSize = transport.maximumMessageSize(otrContact.contact); + if (messageSize + == OperationSetBasicInstantMessagingTransport.UNLIMITED) + { + messageSize = FragmenterInstructions.UNLIMITED; + } + int numberOfMessages = + transport.numberOfMessages(otrContact.contact); + if (numberOfMessages + == OperationSetBasicInstantMessagingTransport.UNLIMITED) + { + numberOfMessages = FragmenterInstructions.UNLIMITED; + } + if (logger.isDebugEnabled()) { - return new FragmenterInstructions( - FragmenterInstructions.UNLIMITED, - FragmenterInstructions.UNLIMITED); + logger.debug("OTR fragmentation instructions for sending a " + + "message to " + otrContact.contact.getDisplayName() + + " (" + otrContact.contact.getAddress() + + "). Maximum number of " + "messages: " + numberOfMessages + + ", maximum message size: " + messageSize); } + return new FragmenterInstructions(numberOfMessages, messageSize); } } diff --git a/src/net/java/sip/communicator/plugin/otr/otr.manifest.mf b/src/net/java/sip/communicator/plugin/otr/otr.manifest.mf index 0dbc56537..07807d412 100644 --- a/src/net/java/sip/communicator/plugin/otr/otr.manifest.mf +++ b/src/net/java/sip/communicator/plugin/otr/otr.manifest.mf @@ -33,5 +33,4 @@ Import-Package: org.osgi.framework, org.bouncycastle.crypto.modes, org.bouncycastle.util, org.bouncycastle.util.encoders, - net.java.sip.communicator.service.msghistory, - net.java.sip.communicator.impl.protocol.irc + net.java.sip.communicator.service.msghistory diff --git a/src/net/java/sip/communicator/service/protocol/OperationSetBasicInstantMessagingTransport.java b/src/net/java/sip/communicator/service/protocol/OperationSetBasicInstantMessagingTransport.java new file mode 100644 index 000000000..cb9526658 --- /dev/null +++ b/src/net/java/sip/communicator/service/protocol/OperationSetBasicInstantMessagingTransport.java @@ -0,0 +1,51 @@ +package net.java.sip.communicator.service.protocol; + +/** + * Provides additional information on the transport on which Basic Instant + * Messaging communication is built. + * + * This interface defines methods that provide information on the transport + * facilities that are used by the Basic Instant Messaging protocol + * implementation. Methods can be used to query the transport channel for + * information such as maximum message sizes and allowed number of consecutive + * messages. + * + * @author Danny van Heumen + */ +public interface OperationSetBasicInstantMessagingTransport + extends OperationSetBasicInstantMessaging +{ + /** + * Constant value indicating unlimited size or number. + */ + int UNLIMITED = -1; + + /** + * Compute the maximum message size for a messaging being sent to the + * provided contact. + * + *

+ * If there is no limit to the message size, please use constant + * {@link #UNLIMITED}. + *

+ * + * @param contact the contact to which the message will be sent + * @return returns the maximum size of the message or UNLIMITED if there is + * no limit + */ + int maximumMessageSize(Contact contact); + + /** + * Compute the maximum number of consecutive messages allowed to be sent to + * this contact. + * + *

+ * If there is no limit to the number of messages, please use constant + * {@link #UNLIMITED}. + *

+ * + * @param contact the contact to which the messages are sent + * @return returns the maximum number of messages to send + */ + int numberOfMessages(Contact contact); +}