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.socks5;

  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.socks5.packet.Bytestream;
  28. import org.jivesoftware.smackx.filetransfer.StreamNegotiator;

  29. /**
  30.  * InitiationListener handles all incoming SOCKS5 Bytestream initiation requests. If there are no
  31.  * listeners for a SOCKS5 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-0065.html#usecase-alternate">XEP-0065</a> Section 5.2.A2).
  34.  *
  35.  * @author Henning Staib
  36.  */
  37. final class InitiationListener extends AbstractIqRequestHandler {
  38.     private static final Logger LOGGER = Logger.getLogger(InitiationListener.class.getName());

  39.     /* manager containing the listeners and the XMPP connection */
  40.     private final Socks5BytestreamManager manager;

  41.     /* executor service to process incoming requests concurrently */
  42.     private final ExecutorService initiationListenerExecutor;

  43.     /**
  44.      * Constructor
  45.      *
  46.      * @param manager the SOCKS5 Bytestream manager
  47.      */
  48.     protected InitiationListener(Socks5BytestreamManager manager) {
  49.         super(Bytestream.ELEMENT, Bytestream.NAMESPACE, IQ.Type.set, Mode.async);
  50.         this.manager = manager;
  51.         initiationListenerExecutor = Executors.newCachedThreadPool();
  52.     }


  53.     @Override
  54.     public IQ handleIQRequest(final IQ packet) {
  55.         initiationListenerExecutor.execute(new Runnable() {

  56.             public void run() {
  57.                 try {
  58.                     processRequest(packet);
  59.                 }
  60.                 catch (InterruptedException | NotConnectedException e) {
  61.                     LOGGER.log(Level.WARNING, "process request", e);
  62.                 }
  63.             }
  64.         });

  65.         return null;
  66.     }

  67.     private void processRequest(Stanza packet) throws NotConnectedException, InterruptedException {
  68.         Bytestream byteStreamRequest = (Bytestream) packet;

  69.         StreamNegotiator.signal(byteStreamRequest.getFrom().toString() + '\t' + byteStreamRequest.getSessionID(), byteStreamRequest);

  70.         // ignore request if in ignore list
  71.         if (this.manager.getIgnoredBytestreamRequests().remove(byteStreamRequest.getSessionID())) {
  72.             return;
  73.         }

  74.         // build bytestream request from packet
  75.         Socks5BytestreamRequest request = new Socks5BytestreamRequest(this.manager,
  76.                         byteStreamRequest);

  77.         // notify listeners for bytestream initiation from a specific user
  78.         BytestreamListener userListener = this.manager.getUserListener(byteStreamRequest.getFrom());
  79.         if (userListener != null) {
  80.             userListener.incomingBytestreamRequest(request);

  81.         }
  82.         else if (!this.manager.getAllRequestListeners().isEmpty()) {
  83.             /*
  84.              * if there is no user specific listener inform listeners for all initiation requests
  85.              */
  86.             for (BytestreamListener listener : this.manager.getAllRequestListeners()) {
  87.                 listener.incomingBytestreamRequest(request);
  88.             }

  89.         }
  90.         else {
  91.             /*
  92.              * if there is no listener for this initiation request, reply with reject message
  93.              */
  94.             this.manager.replyRejectPacket(byteStreamRequest);
  95.         }
  96.     }

  97.     /**
  98.      * Shuts down the listeners executor service.
  99.      */
  100.     protected void shutdown() {
  101.         this.initiationListenerExecutor.shutdownNow();
  102.     }

  103. }