001/** 002 * 003 * Copyright 2003-2006 Jive Software. 004 * 005 * Licensed under the Apache License, Version 2.0 (the "License"); 006 * you may not use this file except in compliance with the License. 007 * You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package org.jivesoftware.smackx.filetransfer; 018 019import java.io.InputStream; 020import java.io.OutputStream; 021 022import org.jivesoftware.smack.SmackException.NoResponseException; 023import org.jivesoftware.smack.SmackException.NotConnectedException; 024import org.jivesoftware.smack.XMPPConnection; 025import org.jivesoftware.smack.XMPPException.XMPPErrorException; 026import org.jivesoftware.smack.packet.Stanza; 027import org.jivesoftware.smackx.bytestreams.ibb.InBandBytestreamManager; 028import org.jivesoftware.smackx.bytestreams.ibb.InBandBytestreamRequest; 029import org.jivesoftware.smackx.bytestreams.ibb.InBandBytestreamSession; 030import org.jivesoftware.smackx.bytestreams.ibb.packet.DataPacketExtension; 031import org.jivesoftware.smackx.bytestreams.ibb.packet.Open; 032import org.jivesoftware.smackx.si.packet.StreamInitiation; 033 034/** 035 * The In-Band Bytestream file transfer method, or IBB for short, transfers the 036 * file over the same XML Stream used by XMPP. It is the fall-back mechanism in 037 * case the SOCKS5 bytestream method of transferring files is not available. 038 * 039 * @author Alexander Wenckus 040 * @author Henning Staib 041 * @see <a href="http://xmpp.org/extensions/xep-0047.html">XEP-0047: In-Band 042 * Bytestreams (IBB)</a> 043 */ 044public class IBBTransferNegotiator extends StreamNegotiator { 045 046 private XMPPConnection connection; 047 048 private InBandBytestreamManager manager; 049 050 /** 051 * The default constructor for the In-Band Bytestream Negotiator. 052 * 053 * @param connection The connection which this negotiator works on. 054 */ 055 protected IBBTransferNegotiator(XMPPConnection connection) { 056 this.connection = connection; 057 this.manager = InBandBytestreamManager.getByteStreamManager(connection); 058 } 059 060 public OutputStream createOutgoingStream(String streamID, String initiator, 061 String target) throws NoResponseException, XMPPErrorException, NotConnectedException { 062 InBandBytestreamSession session = this.manager.establishSession(target, streamID); 063 session.setCloseBothStreamsEnabled(true); 064 return session.getOutputStream(); 065 } 066 067 public InputStream createIncomingStream(StreamInitiation initiation) 068 throws NoResponseException, XMPPErrorException, NotConnectedException { 069 /* 070 * In-Band Bytestream initiation listener must ignore next in-band bytestream request with 071 * given session ID 072 */ 073 this.manager.ignoreBytestreamRequestOnce(initiation.getSessionID()); 074 075 Stanza streamInitiation = initiateIncomingStream(this.connection, initiation); 076 return negotiateIncomingStream(streamInitiation); 077 } 078 079 @Override 080 public void newStreamInitiation(String from, String streamID) { 081 /* 082 * this method is always called prior to #negotiateIncomingStream() so 083 * the In-Band Bytestream initiation listener must ignore the next 084 * In-Band Bytestream request with the given session ID 085 */ 086 this.manager.ignoreBytestreamRequestOnce(streamID); 087 } 088 089 public String[] getNamespaces() { 090 return new String[] { DataPacketExtension.NAMESPACE }; 091 } 092 093 InputStream negotiateIncomingStream(Stanza streamInitiation) throws NotConnectedException { 094 // build In-Band Bytestream request 095 InBandBytestreamRequest request = new ByteStreamRequest(this.manager, 096 (Open) streamInitiation); 097 098 // always accept the request 099 InBandBytestreamSession session = request.accept(); 100 session.setCloseBothStreamsEnabled(true); 101 return session.getInputStream(); 102 } 103 104 /** 105 * Derive from InBandBytestreamRequest to access protected constructor. 106 */ 107 private static class ByteStreamRequest extends InBandBytestreamRequest { 108 109 private ByteStreamRequest(InBandBytestreamManager manager, Open byteStreamRequest) { 110 super(manager, byteStreamRequest); 111 } 112 113 } 114 115}