Home | History | Annotate | Download | only in ibb
      1 /**
      2  * All rights reserved. Licensed under the Apache License, Version 2.0 (the "License");
      3  * you may not use this file except in compliance with the License.
      4  * You may obtain a copy of the License at
      5  *
      6  *     http://www.apache.org/licenses/LICENSE-2.0
      7  *
      8  * Unless required by applicable law or agreed to in writing, software
      9  * distributed under the License is distributed on an "AS IS" BASIS,
     10  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     11  * See the License for the specific language governing permissions and
     12  * limitations under the License.
     13  */
     14 package org.jivesoftware.smackx.bytestreams.ibb;
     15 
     16 import java.util.concurrent.ExecutorService;
     17 import java.util.concurrent.Executors;
     18 
     19 import org.jivesoftware.smack.PacketListener;
     20 import org.jivesoftware.smack.filter.AndFilter;
     21 import org.jivesoftware.smack.filter.IQTypeFilter;
     22 import org.jivesoftware.smack.filter.PacketFilter;
     23 import org.jivesoftware.smack.filter.PacketTypeFilter;
     24 import org.jivesoftware.smack.packet.IQ;
     25 import org.jivesoftware.smack.packet.Packet;
     26 import org.jivesoftware.smackx.bytestreams.BytestreamListener;
     27 import org.jivesoftware.smackx.bytestreams.ibb.packet.Open;
     28 
     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 implements PacketListener {
     42 
     43     /* manager containing the listeners and the XMPP connection */
     44     private final InBandBytestreamManager manager;
     45 
     46     /* packet filter for all In-Band Bytestream requests */
     47     private final PacketFilter initFilter = new AndFilter(new PacketTypeFilter(Open.class),
     48                     new IQTypeFilter(IQ.Type.SET));
     49 
     50     /* executor service to process incoming requests concurrently */
     51     private final ExecutorService initiationListenerExecutor;
     52 
     53     /**
     54      * Constructor.
     55      *
     56      * @param manager the In-Band Bytestream manager
     57      */
     58     protected InitiationListener(InBandBytestreamManager manager) {
     59         this.manager = manager;
     60         initiationListenerExecutor = Executors.newCachedThreadPool();
     61     }
     62 
     63     public void processPacket(final Packet packet) {
     64         initiationListenerExecutor.execute(new Runnable() {
     65 
     66             public void run() {
     67                 processRequest(packet);
     68             }
     69         });
     70     }
     71 
     72     private void processRequest(Packet packet) {
     73         Open ibbRequest = (Open) packet;
     74 
     75         // validate that block size is within allowed range
     76         if (ibbRequest.getBlockSize() > this.manager.getMaximumBlockSize()) {
     77             this.manager.replyResourceConstraintPacket(ibbRequest);
     78             return;
     79         }
     80 
     81         // ignore request if in ignore list
     82         if (this.manager.getIgnoredBytestreamRequests().remove(ibbRequest.getSessionID()))
     83             return;
     84 
     85         // build bytestream request from packet
     86         InBandBytestreamRequest request = new InBandBytestreamRequest(this.manager, ibbRequest);
     87 
     88         // notify listeners for bytestream initiation from a specific user
     89         BytestreamListener userListener = this.manager.getUserListener(ibbRequest.getFrom());
     90         if (userListener != null) {
     91             userListener.incomingBytestreamRequest(request);
     92 
     93         }
     94         else if (!this.manager.getAllRequestListeners().isEmpty()) {
     95             /*
     96              * if there is no user specific listener inform listeners for all initiation requests
     97              */
     98             for (BytestreamListener listener : this.manager.getAllRequestListeners()) {
     99                 listener.incomingBytestreamRequest(request);
    100             }
    101 
    102         }
    103         else {
    104             /*
    105              * if there is no listener for this initiation request, reply with reject message
    106              */
    107             this.manager.replyRejectPacket(ibbRequest);
    108         }
    109     }
    110 
    111     /**
    112      * Returns the packet filter for In-Band Bytestream open requests.
    113      *
    114      * @return the packet filter for In-Band Bytestream open requests
    115      */
    116     protected PacketFilter getFilter() {
    117         return this.initFilter;
    118     }
    119 
    120     /**
    121      * Shuts down the listeners executor service.
    122      */
    123     protected void shutdown() {
    124         this.initiationListenerExecutor.shutdownNow();
    125     }
    126 
    127 }
    128