/** * Add a new Stanza ID acknowledged listener for the given ID. * <p> * The listener will be invoked if the stanza with the given ID was acknowledged by the server. It will * automatically be removed after the listener was run. * </p> * * @param id the stanza ID. * @param listener the listener to invoke. * @return the previous listener for this stanza ID or null. * @throws StreamManagementNotEnabledException if Stream Management is not enabled. */ public StanzaListener addStanzaIdAcknowledgedListener(final String id, StanzaListener listener) throws StreamManagementNotEnabledException { // Prevent users from adding callbacks that will never get removed if (!smWasEnabledAtLeastOnce) { throw new StreamManagementException.StreamManagementNotEnabledException(); } // Remove the listener after max. 12 hours final int removeAfterSeconds = Math.min(getMaxSmResumptionTime(), 12 * 60 * 60); schedule(new Runnable() { @Override public void run() { stanzaIdAcknowledgedListeners.remove(id); } }, removeAfterSeconds, TimeUnit.SECONDS); return stanzaIdAcknowledgedListeners.put(id, listener); }
private MultiUserChatManager(XMPPConnection connection) { super(connection); // Listens for all messages that include a MUCUser extension and fire the invitation // listeners if the message includes an invitation. StanzaListener invitationPacketListener = new StanzaListener() { public void processPacket(Stanza packet) { final Message message = (Message) packet; // Get the MUCUser extension final MUCUser mucUser = MUCUser.from(message); // Check if the MUCUser extension includes an invitation if (mucUser.getInvite() != null) { // Fire event for invitation listeners final MultiUserChat muc = getMultiUserChat(packet.getFrom()); for (final InvitationListener listener : invitationsListeners) { listener.invitationReceived(connection(), muc, mucUser.getInvite().getFrom(), mucUser.getInvite().getReason(), mucUser.getPassword(), message); } } } }; connection.addAsyncStanzaListener(invitationPacketListener, INVITATION_FILTER); }
/** * Valid data packets should be confirmed. * * @throws Exception should not happen */ @Test public void shouldConfirmReceivedDataPacket() throws Exception { // verify data packet confirmation is of type RESULT protocol.addResponse(null, Verification.requestTypeRESULT); InBandBytestreamSession session = new InBandBytestreamSession(connection, initBytestream, initiatorJID); InputStream inputStream = session.getInputStream(); StanzaListener listener = Whitebox.getInternalState(inputStream, StanzaListener.class); String base64Data = Base64.encode("Data"); DataPacketExtension dpe = new DataPacketExtension(sessionID, 0, base64Data); Data data = new Data(dpe); listener.processPacket(data); protocol.verifyAll(); }
private void sendPushRegistration(final String regId) { IQ iq = PushRegistration.register(DEFAULT_PUSH_PROVIDER, regId); try { iq.setTo(JidCreate.from("push", mServer.getNetwork(), "")); } catch (XmppStringprepException e) { Log.w(TAG, "error parsing JID: " + e.getCausingString(), e); // report it because it's a big deal ReportingManager.logException(e); return; } sendIqWithReply(iq, true, new StanzaListener() { @Override public void processStanza(Stanza packet) throws NotConnectedException { if (mPushService != null) mPushService.setRegisteredOnServer(regId != null); } }, null); }
private void sendPushUnregistration() { IQ iq = PushRegistration.unregister(DEFAULT_PUSH_PROVIDER); try { iq.setTo(JidCreate.from("push", mServer.getNetwork(), "")); } catch (XmppStringprepException e) { Log.w(TAG, "error parsing JID: " + e.getCausingString(), e); // report it because it's a big deal ReportingManager.logException(e); return; } sendIqWithReply(iq, true, new StanzaListener() { @Override public void processStanza(Stanza packet) throws NotConnectedException { if (mPushService != null) mPushService.setRegisteredOnServer(false); } }, null); }
/** * Notify server to change the carbons state. This method returns * immediately and changes the variable when the reply arrives. * * You should first check for support using isSupportedByServer(). * * @param new_state whether carbons should be enabled or disabled * @throws NotConnectedException */ public void sendCarbonsEnabled(final boolean new_state) throws NotConnectedException { IQ setIQ = carbonsEnabledIQ(new_state); connection().sendIqWithResponseCallback(setIQ, new StanzaListener() { public void processPacket(Stanza packet) { enabled_state = new_state; } }); }
/** * Creates a new roster exchange manager. * * @param connection an XMPPConnection which is used to send and receive messages. */ public RosterExchangeManager(XMPPConnection connection) { weakRefConnection = new WeakReference<XMPPConnection>(connection); // Listens for all roster exchange packets and fire the roster exchange listeners. packetListener = new StanzaListener() { public void processPacket(Stanza packet) { Message message = (Message) packet; RosterExchange rosterExchange = (RosterExchange) message.getExtension(ELEMENT, NAMESPACE); // Fire event for roster exchange listeners fireRosterExchangeListeners(message.getFrom(), rosterExchange.getRosterEntries()); } }; connection.addAsyncStanzaListener(packetListener, PACKET_FILTER); }
private ChatManager(XMPPConnection connection) { super(connection); // Add a listener for all message packets so that we can deliver // messages to the best Chat instance available. connection.addSyncStanzaListener(new StanzaListener() { public void processPacket(Stanza packet) { Message message = (Message) packet; Chat chat; if (message.getThread() == null) { chat = getUserChat(message.getFrom()); } else { chat = getThreadChat(message.getThread()); } if(chat == null) { chat = createChat(message); } // The chat could not be created, abort here if (chat == null) return; deliverMessage(chat, message); } }, packetFilter); INSTANCES.put(connection, this); }
/** * Register a listener for item publication events. This * listener will get called whenever an item is published to * this node. * * @param listener The handler for the event */ @SuppressWarnings("unchecked") public void addItemEventListener(@SuppressWarnings("rawtypes") ItemEventListener listener) { StanzaListener conListener = new ItemEventTranslator(listener); itemEventToListenerMap.put(listener, conListener); con.addSyncStanzaListener(conListener, new EventContentFilter(EventElementType.items.toString(), "item")); }
/** * Unregister a listener for publication events. * * @param listener The handler to unregister */ public void removeItemEventListener(@SuppressWarnings("rawtypes") ItemEventListener listener) { StanzaListener conListener = itemEventToListenerMap.remove(listener); if (conListener != null) con.removeSyncStanzaListener(conListener); }
/** * Register a listener for configuration events. This listener * will get called whenever the node's configuration changes. * * @param listener The handler for the event */ public void addConfigurationListener(NodeConfigListener listener) { StanzaListener conListener = new NodeConfigTranslator(listener); configEventToListenerMap.put(listener, conListener); con.addSyncStanzaListener(conListener, new EventContentFilter(EventElementType.configuration.toString())); }
/** * Unregister a listener for configuration events. * * @param listener The handler to unregister */ public void removeConfigurationListener(NodeConfigListener listener) { StanzaListener conListener = configEventToListenerMap .remove(listener); if (conListener != null) con.removeSyncStanzaListener(conListener); }
/** * Register an listener for item delete events. This listener * gets called whenever an item is deleted from the node. * * @param listener The handler for the event */ public void addItemDeleteListener(ItemDeleteListener listener) { StanzaListener delListener = new ItemDeleteTranslator(listener); itemDeleteToListenerMap.put(listener, delListener); EventContentFilter deleteItem = new EventContentFilter(EventElementType.items.toString(), "retract"); EventContentFilter purge = new EventContentFilter(EventElementType.purge.toString()); con.addSyncStanzaListener(delListener, new OrFilter(deleteItem, purge)); }
/** * Unregister a listener for item delete events. * * @param listener The handler to unregister */ public void removeItemDeleteListener(ItemDeleteListener listener) { StanzaListener conListener = itemDeleteToListenerMap .remove(listener); if (conListener != null) con.removeSyncStanzaListener(conListener); }
protected StanzaListener getDataPacketListener() { return new StanzaListener() { public void processPacket(Stanza packet) { // get data packet extension DataPacketExtension data = (DataPacketExtension) packet.getExtension( DataPacketExtension.ELEMENT, DataPacketExtension.NAMESPACE); // check if encoded data is valid if (data.getDecodedData() == null) { /* * TODO once a majority of XMPP server implementation support XEP-0079 * Advanced Message Processing the invalid message could be answered with an * appropriate error. For now we just ignore the packet. Subsequent packets * with an increased sequence will cause the input stream to close the * stream/session. */ return; } // data is valid; add to data queue dataQueue.offer(data); // TODO confirm packet once XMPP servers support XEP-0079 } }; }
private void init() { // Listens for all roster exchange packets and fire the roster exchange listeners. packetListener = new StanzaListener() { public void processPacket(Stanza packet) { Message message = (Message) packet; PEPEvent event = (PEPEvent) message.getExtension("event", "http://jabber.org/protocol/pubsub#event"); // Fire event for roster exchange listeners firePEPListeners(message.getFrom(), event); } }; connection.addSyncStanzaListener(packetListener, packetFilter); }
/** * If a data stanza(/packet) is received out of order the session should be closed. See XEP-0047 Section * 2.2. * * @throws Exception should not happen */ @Test public void shouldSendCloseRequestIfInvalidSequenceReceived() throws Exception { // confirm close request IQ resultIQ = IBBPacketUtils.createResultIQ(initiatorJID, targetJID); protocol.addResponse(resultIQ, Verification.requestTypeSET, Verification.correspondingSenderReceiver); // get IBB sessions data packet listener InBandBytestreamSession session = new InBandBytestreamSession(connection, initBytestream, initiatorJID); InputStream inputStream = session.getInputStream(); StanzaListener listener = Whitebox.getInternalState(inputStream, StanzaListener.class); // build invalid packet with out of order sequence String base64Data = Base64.encode("Data"); DataPacketExtension dpe = new DataPacketExtension(sessionID, 123, base64Data); Message dataMessage = new Message(); dataMessage.addExtension(dpe); // add data packets listener.processPacket(dataMessage); // read until exception is thrown try { inputStream.read(); fail("exception should be thrown"); } catch (IOException e) { assertTrue(e.getMessage().contains("Packets out of sequence")); } protocol.verifyAll(); }
/** * Test the input stream read(byte[], int, int) method. * * @throws Exception should not happen */ @Test public void shouldReadAllReceivedData1() throws Exception { // create random data Random rand = new Random(); byte[] controlData = new byte[3 * blockSize]; rand.nextBytes(controlData); // get IBB sessions data packet listener InBandBytestreamSession session = new InBandBytestreamSession(connection, initBytestream, initiatorJID); InputStream inputStream = session.getInputStream(); StanzaListener listener = Whitebox.getInternalState(inputStream, StanzaListener.class); // verify data packet and notify listener for (int i = 0; i < controlData.length / blockSize; i++) { String base64Data = Base64.encodeToString(controlData, i * blockSize, blockSize); DataPacketExtension dpe = new DataPacketExtension(sessionID, i, base64Data); Message dataMessage = new Message(); dataMessage.addExtension(dpe); listener.processPacket(dataMessage); } byte[] bytes = new byte[3 * blockSize]; int read = 0; read = inputStream.read(bytes, 0, blockSize); assertEquals(blockSize, read); read = inputStream.read(bytes, 10, blockSize); assertEquals(blockSize, read); read = inputStream.read(bytes, 20, blockSize); assertEquals(blockSize, read); // verify data for (int i = 0; i < bytes.length; i++) { assertEquals(controlData[i], bytes[i]); } protocol.verifyAll(); }
/** * Test the input stream read() method. * * @throws Exception should not happen */ @Test public void shouldReadAllReceivedData2() throws Exception { // create random data Random rand = new Random(); byte[] controlData = new byte[3 * blockSize]; rand.nextBytes(controlData); // get IBB sessions data packet listener InBandBytestreamSession session = new InBandBytestreamSession(connection, initBytestream, initiatorJID); InputStream inputStream = session.getInputStream(); StanzaListener listener = Whitebox.getInternalState(inputStream, StanzaListener.class); // verify data packet and notify listener for (int i = 0; i < controlData.length / blockSize; i++) { String base64Data = Base64.encodeToString(controlData, i * blockSize, blockSize); DataPacketExtension dpe = new DataPacketExtension(sessionID, i, base64Data); Message dataMessage = new Message(); dataMessage.addExtension(dpe); listener.processPacket(dataMessage); } // read data byte[] bytes = new byte[3 * blockSize]; for (int i = 0; i < bytes.length; i++) { bytes[i] = (byte) inputStream.read(); } // verify data for (int i = 0; i < bytes.length; i++) { assertEquals(controlData[i], bytes[i]); } protocol.verifyAll(); }
/** * If the input stream is closed the output stream should not be closed as well. * * @throws Exception should not happen */ @Test public void shouldNotCloseBothStreamsIfOutputStreamIsClosed() throws Exception { InBandBytestreamSession session = new InBandBytestreamSession(connection, initBytestream, initiatorJID); OutputStream outputStream = session.getOutputStream(); outputStream.close(); // verify data packet confirmation is of type RESULT protocol.addResponse(null, Verification.requestTypeRESULT); // insert data to read InputStream inputStream = session.getInputStream(); StanzaListener listener = Whitebox.getInternalState(inputStream, StanzaListener.class); String base64Data = Base64.encode("Data"); DataPacketExtension dpe = new DataPacketExtension(sessionID, 0, base64Data); Data data = new Data(dpe); listener.processPacket(data); // verify no packet send protocol.verifyAll(); try { outputStream.flush(); fail("should throw an exception"); } catch (IOException e) { assertTrue(e.getMessage().contains("closed")); } assertTrue(inputStream.read() != 0); }
/** * If the data stanza(/packet) has a sequence that is already used an 'unexpected-request' error should * be returned. See XEP-0047 Section 2.2. * * @throws Exception should not happen */ @Test public void shouldReplyWithErrorIfAlreadyUsedSequenceIsReceived() throws Exception { // verify reply to first valid data packet is of type RESULT protocol.addResponse(null, Verification.requestTypeRESULT); // verify reply to invalid data packet is an error protocol.addResponse(null, Verification.requestTypeERROR, new Verification<IQ, IQ>() { public void verify(IQ request, IQ response) { assertEquals(XMPPError.Condition.unexpected_request, request.getError().getCondition()); } }); // get IBB sessions data packet listener InBandBytestreamSession session = new InBandBytestreamSession(connection, initBytestream, initiatorJID); InputStream inputStream = session.getInputStream(); StanzaListener listener = Whitebox.getInternalState(inputStream, StanzaListener.class); // build data packets String base64Data = Base64.encode("Data"); DataPacketExtension dpe = new DataPacketExtension(sessionID, 0, base64Data); Data data1 = new Data(dpe); Data data2 = new Data(dpe); // notify listener listener.processPacket(data1); listener.processPacket(data2); protocol.verifyAll(); }
/** * If the data stanza(/packet) contains invalid Base64 encoding an 'bad-request' error should be * returned. See XEP-0047 Section 2.2. * * @throws Exception should not happen */ @Test public void shouldReplyWithErrorIfDataIsInvalid() throws Exception { // verify reply to invalid data packet is an error protocol.addResponse(null, Verification.requestTypeERROR, new Verification<IQ, IQ>() { public void verify(IQ request, IQ response) { assertEquals(XMPPError.Condition.bad_request, request.getError().getCondition()); } }); // get IBB sessions data packet listener InBandBytestreamSession session = new InBandBytestreamSession(connection, initBytestream, initiatorJID); InputStream inputStream = session.getInputStream(); StanzaListener listener = Whitebox.getInternalState(inputStream, StanzaListener.class); // build data packets DataPacketExtension dpe = new DataPacketExtension(sessionID, 0, "AA=BB"); Data data = new Data(dpe); // notify listener listener.processPacket(data); protocol.verifyAll(); }
/** * If a data stanza(/packet) is received out of order the session should be closed. See XEP-0047 Section * 2.2. * * @throws Exception should not happen */ @Test public void shouldSendCloseRequestIfInvalidSequenceReceived() throws Exception { IQ resultIQ = IBBPacketUtils.createResultIQ(initiatorJID, targetJID); // confirm data packet with invalid sequence protocol.addResponse(resultIQ); // confirm close request protocol.addResponse(resultIQ, Verification.requestTypeSET, Verification.correspondingSenderReceiver); // get IBB sessions data packet listener InBandBytestreamSession session = new InBandBytestreamSession(connection, initBytestream, initiatorJID); InputStream inputStream = session.getInputStream(); StanzaListener listener = Whitebox.getInternalState(inputStream, StanzaListener.class); // build invalid packet with out of order sequence String base64Data = Base64.encode("Data"); DataPacketExtension dpe = new DataPacketExtension(sessionID, 123, base64Data); Data data = new Data(dpe); // add data packets listener.processPacket(data); // read until exception is thrown try { inputStream.read(); fail("exception should be thrown"); } catch (IOException e) { assertTrue(e.getMessage().contains("Packets out of sequence")); } protocol.verifyAll(); }
/** * Test the input stream read() method. * * @throws Exception should not happen */ @Test public void shouldReadAllReceivedData2() throws Exception { // create random data Random rand = new Random(); byte[] controlData = new byte[3 * blockSize]; rand.nextBytes(controlData); IQ resultIQ = IBBPacketUtils.createResultIQ(initiatorJID, targetJID); // get IBB sessions data packet listener InBandBytestreamSession session = new InBandBytestreamSession(connection, initBytestream, initiatorJID); InputStream inputStream = session.getInputStream(); StanzaListener listener = Whitebox.getInternalState(inputStream, StanzaListener.class); // set data packet acknowledgment and notify listener for (int i = 0; i < controlData.length / blockSize; i++) { protocol.addResponse(resultIQ); String base64Data = Base64.encodeToString(controlData, i * blockSize, blockSize); DataPacketExtension dpe = new DataPacketExtension(sessionID, i, base64Data); Data data = new Data(dpe); listener.processPacket(data); } // read data byte[] bytes = new byte[3 * blockSize]; for (int i = 0; i < bytes.length; i++) { bytes[i] = (byte) inputStream.read(); } // verify data for (int i = 0; i < bytes.length; i++) { assertEquals(controlData[i], bytes[i]); } protocol.verifyAll(); }
/** * If the output stream is closed the input stream should not be closed as well. * * @throws Exception should not happen */ @Test public void shouldNotCloseBothStreamsIfInputStreamIsClosed() throws Exception { // acknowledgment for data packet IQ resultIQ = IBBPacketUtils.createResultIQ(initiatorJID, targetJID); protocol.addResponse(resultIQ); // get IBB sessions data packet listener InBandBytestreamSession session = new InBandBytestreamSession(connection, initBytestream, initiatorJID); InputStream inputStream = session.getInputStream(); StanzaListener listener = Whitebox.getInternalState(inputStream, StanzaListener.class); // build data packet String base64Data = Base64.encode("Data"); DataPacketExtension dpe = new DataPacketExtension(sessionID, 0, base64Data); Data data = new Data(dpe); // add data packets listener.processPacket(data); inputStream.close(); protocol.verifyAll(); try { while (inputStream.read() != -1) { } inputStream.read(); fail("should throw an exception"); } catch (IOException e) { assertTrue(e.getMessage().contains("closed")); } session.getOutputStream().flush(); }
/** * Register the listenerJingles, waiting for a Jingle stanza(/packet) that tries to * establish a new session. */ private void initJingleSessionRequestListeners() { StanzaFilter initRequestFilter = new StanzaFilter() { // Return true if we accept this packet public boolean accept(Stanza pin) { if (pin instanceof IQ) { IQ iq = (IQ) pin; if (iq.getType().equals(IQ.Type.set)) { if (iq instanceof Jingle) { Jingle jin = (Jingle) pin; if (jin.getAction().equals(JingleActionEnum.SESSION_INITIATE)) { return true; } } } } return false; } }; jingleSessionRequestListeners = new ArrayList<JingleSessionRequestListener>(); // Start a packet listener for session initiation requests connection.addAsyncStanzaListener(new StanzaListener() { public void processPacket(Stanza packet) { triggerSessionRequested((Jingle) packet); } }, initRequestFilter); }
@CommandHandler(name = ACTION_SERVERLIST) private boolean handleServerList(boolean canConnect) { if (canConnect && isConnected()) { ServerlistCommand p = new ServerlistCommand(); p.setTo(XmppStringUtils.completeJidFrom("network", mServer.getNetwork())); StanzaFilter filter = new StanzaIdFilter(p.getStanzaId()); // TODO cache the listener (it shouldn't change) mConnection.addAsyncStanzaListener(new StanzaListener() { public void processStanza(Stanza packet) throws NotConnectedException { Intent i = new Intent(ACTION_SERVERLIST); List<String> _items = ((ServerlistCommand.ServerlistCommandData) packet) .getItems(); if (_items != null && _items.size() != 0 && packet.getError() == null) { String[] items = new String[_items.size()]; _items.toArray(items); i.putExtra(EXTRA_FROM, packet.getFrom().toString()); i.putExtra(EXTRA_JIDLIST, items); } mLocalBroadcastManager.sendBroadcast(i); } }, filter); sendPacket(p); } return false; }
synchronized AttachmentManager.Slot getSlot(String filename, long size, String mime) { HTTPFileUpload.Request request = new HTTPFileUpload.Request(filename, size, mime); request.setTo(mService.toBareSmack()); final Callback.Synchronizer syncer = new Callback.Synchronizer(); mSlotPacket = null; mConn.sendWithCallback(request, new StanzaListener() { @Override public void processStanza(Stanza packet) throws SmackException.NotConnectedException { LOGGER.config("response: "+packet); if (!(packet instanceof HTTPFileUpload.Slot)) { LOGGER.warning("response not a slot packet: "+packet); syncer.sync(); return; } mSlotPacket = (HTTPFileUpload.Slot) packet; syncer.sync(); } }); syncer.waitForSync(); return mSlotPacket != null ? new AttachmentManager.Slot( EncodingUtils.toURI(mSlotPacket.getPutUrl()), EncodingUtils.toURI(mSlotPacket.getGetUrl())) : new AttachmentManager.Slot(); }
public HandleChatPacketListener(XMPPService xmppService) { mXMPPService = xmppService; mSettings = Settings.getInstance(xmppService.getContext()); mChatPacketListener = new StanzaListener() { @Override public void processStanza(Stanza packet) { Message message = (Message) packet; Jid from = message.getFrom(); if (MAXSElement.foundIn(packet)) { // Ignore messages with a MAXS element. This is done to prevent endless loops of // message sending between one or multiple MAXS instances. LOG.w("Ignoring message with MAXS element. jid='" + from + "' message='" + message + '\''); return; } if (mSettings.isMasterJID(from)) { mXMPPService.newMessageFromMasterJID(message); } else { LOG.w("Ignoring message from non-master JID: jid='" + from + "' message='" + message + '\''); } } }; }
@Override public StanzaListener getReaderListener() { return receivedListener; }
@Override public StanzaListener getWriterListener() { return sentListener; }
public StanzaListener getReaderListener() { return listener; }
public StanzaListener getWriterListener() { return null; }
public StanzaListener getReaderListener() { return packetReaderListener; }
public StanzaListener getWriterListener() { return packetWriterListener; }
protected StanzaListener getDataPacketListener() { return new StanzaListener() { private long lastSequence = -1; public void processPacket(Stanza packet) throws NotConnectedException { // get data packet extension DataPacketExtension data = ((Data) packet).getDataPacketExtension(); /* * check if sequence was not used already (see XEP-0047 Section 2.2) */ if (data.getSeq() <= this.lastSequence) { IQ unexpectedRequest = IQ.createErrorResponse((IQ) packet, new XMPPError( XMPPError.Condition.unexpected_request)); connection.sendStanza(unexpectedRequest); return; } // check if encoded data is valid (see XEP-0047 Section 2.2) if (data.getDecodedData() == null) { // data is invalid; respond with bad-request error IQ badRequest = IQ.createErrorResponse((IQ) packet, new XMPPError( XMPPError.Condition.bad_request)); connection.sendStanza(badRequest); return; } // data is valid; add to data queue dataQueue.offer(data); // confirm IQ IQ confirmData = IQ.createResultIQ((IQ) packet); connection.sendStanza(confirmData); // set last seen sequence this.lastSequence = data.getSeq(); if (this.lastSequence == 65535) { this.lastSequence = -1; } } }; }