InitiationListener.java

  1. /**
  2.  *
  3.  * Copyright the original author or authors
  4.  *
  5.  * Licensed under the Apache License, Version 2.0 (the "License");
  6.  * you may not use this file except in compliance with the License.
  7.  * You may obtain a copy of the License at
  8.  *
  9.  *     http://www.apache.org/licenses/LICENSE-2.0
  10.  *
  11.  * Unless required by applicable law or agreed to in writing, software
  12.  * distributed under the License is distributed on an "AS IS" BASIS,
  13.  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14.  * See the License for the specific language governing permissions and
  15.  * limitations under the License.
  16.  */
  17. package org.jivesoftware.smackx.bytestreams.ibb;

  18. import java.util.concurrent.ExecutorService;
  19. import java.util.concurrent.Executors;
  20. import java.util.logging.Level;
  21. import java.util.logging.Logger;

  22. import org.jivesoftware.smack.SmackException.NotConnectedException;
  23. import org.jivesoftware.smack.iqrequest.AbstractIqRequestHandler;
  24. import org.jivesoftware.smack.packet.IQ;
  25. import org.jivesoftware.smack.packet.Stanza;
  26. import org.jivesoftware.smackx.bytestreams.BytestreamListener;
  27. import org.jivesoftware.smackx.bytestreams.ibb.packet.Open;
  28. import org.jivesoftware.smackx.filetransfer.StreamNegotiator;


  29. /**
  30.  * InitiationListener handles all incoming In-Band Bytestream open requests. If there are no
  31.  * listeners for a In-Band Bytestream request InitiationListener will always refuse the request and
  32.  * reply with a &lt;not-acceptable/&gt; error (<a
  33.  * href="http://xmpp.org/extensions/xep-0047.html#example-5" >XEP-0047</a> Section 2.1).
  34.  * <p>
  35.  * All In-Band Bytestream request having a block size greater than the maximum allowed block size
  36.  * for this connection are rejected with an &lt;resource-constraint/&gt; error. The maximum block
  37.  * size can be set by invoking {@link InBandBytestreamManager#setMaximumBlockSize(int)}.
  38.  *
  39.  * @author Henning Staib
  40.  */
  41. class InitiationListener extends AbstractIqRequestHandler {
  42.     private static final Logger LOGGER = Logger.getLogger(InitiationListener.class.getName());

  43.     /* manager containing the listeners and the XMPP connection */
  44.     private final InBandBytestreamManager manager;

  45.     /* executor service to process incoming requests concurrently */
  46.     private final ExecutorService initiationListenerExecutor;

  47.     /**
  48.      * Constructor.
  49.      *
  50.      * @param manager the In-Band Bytestream manager
  51.      */
  52.     protected InitiationListener(InBandBytestreamManager manager) {
  53.         super(Open.ELEMENT, Open.NAMESPACE, IQ.Type.set, Mode.async);
  54.         this.manager = manager;
  55.         initiationListenerExecutor = Executors.newCachedThreadPool();
  56.      }

  57.     @Override
  58.     public IQ handleIQRequest(final IQ packet) {
  59.         initiationListenerExecutor.execute(new Runnable() {

  60.             public void run() {
  61.                 try {
  62.                     processRequest(packet);
  63.                 }
  64.                 catch (InterruptedException | NotConnectedException e) {
  65.                     LOGGER.log(Level.WARNING, "proccessRequest", e);
  66.                 }
  67.             }
  68.         });
  69.         return null;
  70.     }

  71.     private void processRequest(Stanza packet) throws NotConnectedException, InterruptedException {
  72.         Open ibbRequest = (Open) packet;

  73.         // validate that block size is within allowed range
  74.         if (ibbRequest.getBlockSize() > this.manager.getMaximumBlockSize()) {
  75.             this.manager.replyResourceConstraintPacket(ibbRequest);
  76.             return;
  77.         }

  78.         StreamNegotiator.signal(ibbRequest.getFrom().toString() + '\t' + ibbRequest.getSessionID(), ibbRequest);

  79.         // ignore request if in ignore list
  80.         if (this.manager.getIgnoredBytestreamRequests().remove(ibbRequest.getSessionID()))
  81.             return;

  82.         // build bytestream request from packet
  83.         InBandBytestreamRequest request = new InBandBytestreamRequest(this.manager, ibbRequest);

  84.         // notify listeners for bytestream initiation from a specific user
  85.         BytestreamListener userListener = this.manager.getUserListener(ibbRequest.getFrom());
  86.         if (userListener != null) {
  87.             userListener.incomingBytestreamRequest(request);

  88.         }
  89.         else if (!this.manager.getAllRequestListeners().isEmpty()) {
  90.             /*
  91.              * if there is no user specific listener inform listeners for all initiation requests
  92.              */
  93.             for (BytestreamListener listener : this.manager.getAllRequestListeners()) {
  94.                 listener.incomingBytestreamRequest(request);
  95.             }

  96.         }
  97.         else {
  98.             /*
  99.              * if there is no listener for this initiation request, reply with reject message
  100.              */
  101.             this.manager.replyRejectPacket(ibbRequest);
  102.         }
  103.     }

  104.     /**
  105.      * Shuts down the listeners executor service.
  106.      */
  107.     protected void shutdown() {
  108.         this.initiationListenerExecutor.shutdownNow();
  109.     }

  110. }