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.socks5; 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.socks5.packet.Bytestream; 28 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 <not-acceptable/> 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 implements PacketListener { 38 39 /* manager containing the listeners and the XMPP connection */ 40 private final Socks5BytestreamManager manager; 41 42 /* packet filter for all SOCKS5 Bytestream requests */ 43 private final PacketFilter initFilter = new AndFilter(new PacketTypeFilter(Bytestream.class), 44 new IQTypeFilter(IQ.Type.SET)); 45 46 /* executor service to process incoming requests concurrently */ 47 private final ExecutorService initiationListenerExecutor; 48 49 /** 50 * Constructor 51 * 52 * @param manager the SOCKS5 Bytestream manager 53 */ 54 protected InitiationListener(Socks5BytestreamManager manager) { 55 this.manager = manager; 56 initiationListenerExecutor = Executors.newCachedThreadPool(); 57 } 58 59 public void processPacket(final Packet packet) { 60 initiationListenerExecutor.execute(new Runnable() { 61 62 public void run() { 63 processRequest(packet); 64 } 65 }); 66 } 67 68 private void processRequest(Packet packet) { 69 Bytestream byteStreamRequest = (Bytestream) packet; 70 71 // ignore request if in ignore list 72 if (this.manager.getIgnoredBytestreamRequests().remove(byteStreamRequest.getSessionID())) { 73 return; 74 } 75 76 // build bytestream request from packet 77 Socks5BytestreamRequest request = new Socks5BytestreamRequest(this.manager, 78 byteStreamRequest); 79 80 // notify listeners for bytestream initiation from a specific user 81 BytestreamListener userListener = this.manager.getUserListener(byteStreamRequest.getFrom()); 82 if (userListener != null) { 83 userListener.incomingBytestreamRequest(request); 84 85 } 86 else if (!this.manager.getAllRequestListeners().isEmpty()) { 87 /* 88 * if there is no user specific listener inform listeners for all initiation requests 89 */ 90 for (BytestreamListener listener : this.manager.getAllRequestListeners()) { 91 listener.incomingBytestreamRequest(request); 92 } 93 94 } 95 else { 96 /* 97 * if there is no listener for this initiation request, reply with reject message 98 */ 99 this.manager.replyRejectPacket(byteStreamRequest); 100 } 101 } 102 103 /** 104 * Returns the packet filter for SOCKS5 Bytestream initialization requests. 105 * 106 * @return the packet filter for SOCKS5 Bytestream initialization requests 107 */ 108 protected PacketFilter getFilter() { 109 return this.initFilter; 110 } 111 112 /** 113 * Shuts down the listeners executor service. 114 */ 115 protected void shutdown() { 116 this.initiationListenerExecutor.shutdownNow(); 117 } 118 119 } 120