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 */ 14package org.jivesoftware.smackx.bytestreams.socks5; 15 16import java.io.IOException; 17import java.net.Socket; 18import java.util.concurrent.TimeoutException; 19 20import org.jivesoftware.smack.Connection; 21import org.jivesoftware.smack.XMPPException; 22import org.jivesoftware.smack.packet.IQ; 23import org.jivesoftware.smack.util.SyncPacketSend; 24import org.jivesoftware.smackx.bytestreams.socks5.packet.Bytestream; 25import org.jivesoftware.smackx.bytestreams.socks5.packet.Bytestream.StreamHost; 26 27/** 28 * Implementation of a SOCKS5 client used on the initiators side. This is needed because connecting 29 * to the local SOCKS5 proxy differs form the regular way to connect to a SOCKS5 proxy. Additionally 30 * a remote SOCKS5 proxy has to be activated by the initiator before data can be transferred between 31 * the peers. 32 * 33 * @author Henning Staib 34 */ 35class Socks5ClientForInitiator extends Socks5Client { 36 37 /* the XMPP connection used to communicate with the SOCKS5 proxy */ 38 private Connection connection; 39 40 /* the session ID used to activate SOCKS5 stream */ 41 private String sessionID; 42 43 /* the target JID used to activate SOCKS5 stream */ 44 private String target; 45 46 /** 47 * Creates a new SOCKS5 client for the initiators side. 48 * 49 * @param streamHost containing network settings of the SOCKS5 proxy 50 * @param digest identifying the SOCKS5 Bytestream 51 * @param connection the XMPP connection 52 * @param sessionID the session ID of the SOCKS5 Bytestream 53 * @param target the target JID of the SOCKS5 Bytestream 54 */ 55 public Socks5ClientForInitiator(StreamHost streamHost, String digest, Connection connection, 56 String sessionID, String target) { 57 super(streamHost, digest); 58 this.connection = connection; 59 this.sessionID = sessionID; 60 this.target = target; 61 } 62 63 public Socket getSocket(int timeout) throws IOException, XMPPException, InterruptedException, 64 TimeoutException { 65 Socket socket = null; 66 67 // check if stream host is the local SOCKS5 proxy 68 if (this.streamHost.getJID().equals(this.connection.getUser())) { 69 Socks5Proxy socks5Server = Socks5Proxy.getSocks5Proxy(); 70 socket = socks5Server.getSocket(this.digest); 71 if (socket == null) { 72 throw new XMPPException("target is not connected to SOCKS5 proxy"); 73 } 74 } 75 else { 76 socket = super.getSocket(timeout); 77 78 try { 79 activate(); 80 } 81 catch (XMPPException e) { 82 socket.close(); 83 throw new XMPPException("activating SOCKS5 Bytestream failed", e); 84 } 85 86 } 87 88 return socket; 89 } 90 91 /** 92 * Activates the SOCKS5 Bytestream by sending a XMPP SOCKS5 Bytestream activation packet to the 93 * SOCKS5 proxy. 94 */ 95 private void activate() throws XMPPException { 96 Bytestream activate = createStreamHostActivation(); 97 // if activation fails #getReply throws an exception 98 SyncPacketSend.getReply(this.connection, activate); 99 } 100 101 /** 102 * Returns a SOCKS5 Bytestream activation packet. 103 * 104 * @return SOCKS5 Bytestream activation packet 105 */ 106 private Bytestream createStreamHostActivation() { 107 Bytestream activate = new Bytestream(this.sessionID); 108 activate.setMode(null); 109 activate.setType(IQ.Type.SET); 110 activate.setTo(this.streamHost.getJID()); 111 112 activate.setToActivate(this.target); 113 114 return activate; 115 } 116 117} 118