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; 027 028import org.jivesoftware.smackx.bytestreams.ibb.InBandBytestreamManager; 029import org.jivesoftware.smackx.bytestreams.ibb.InBandBytestreamRequest; 030import org.jivesoftware.smackx.bytestreams.ibb.InBandBytestreamSession; 031import org.jivesoftware.smackx.bytestreams.ibb.packet.DataPacketExtension; 032import org.jivesoftware.smackx.bytestreams.ibb.packet.Open; 033import org.jivesoftware.smackx.si.packet.StreamInitiation; 034 035import org.jxmpp.jid.Jid; 036 037/** 038 * The In-Band Bytestream file transfer method, or IBB for short, transfers the 039 * file over the same XML Stream used by XMPP. It is the fall-back mechanism in 040 * case the SOCKS5 bytestream method of transferring files is not available. 041 * 042 * @author Alexander Wenckus 043 * @author Henning Staib 044 * @see <a href="http://xmpp.org/extensions/xep-0047.html">XEP-0047: In-Band 045 * Bytestreams (IBB)</a> 046 */ 047public class IBBTransferNegotiator extends StreamNegotiator { 048 049 private final InBandBytestreamManager manager; 050 051 /** 052 * The default constructor for the In-Band Bytestream Negotiator. 053 * 054 * @param connection The connection which this negotiator works on. 055 */ 056 protected IBBTransferNegotiator(XMPPConnection connection) { 057 super(connection); 058 this.manager = InBandBytestreamManager.getByteStreamManager(connection); 059 } 060 061 @Override 062 public OutputStream createOutgoingStream(String streamID, Jid initiator, 063 Jid target) throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException { 064 InBandBytestreamSession session = this.manager.establishSession(target, streamID); 065 session.setCloseBothStreamsEnabled(true); 066 return session.getOutputStream(); 067 } 068 069 @Override 070 public InputStream createIncomingStream(StreamInitiation initiation) 071 throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException { 072 /* 073 * In-Band Bytestream initiation listener must ignore next in-band bytestream request with 074 * given session ID 075 */ 076 this.manager.ignoreBytestreamRequestOnce(initiation.getSessionID()); 077 078 Stanza streamInitiation = initiateIncomingStream(connection(), initiation); 079 return negotiateIncomingStream(streamInitiation); 080 } 081 082 @Override 083 public void newStreamInitiation(Jid from, String streamID) { 084 /* 085 * this method is always called prior to #negotiateIncomingStream() so 086 * the In-Band Bytestream initiation listener must ignore the next 087 * In-Band Bytestream request with the given session ID 088 */ 089 this.manager.ignoreBytestreamRequestOnce(streamID); 090 } 091 092 @Override 093 public String[] getNamespaces() { 094 return new String[] { DataPacketExtension.NAMESPACE }; 095 } 096 097 @Override 098 InputStream negotiateIncomingStream(Stanza streamInitiation) throws NotConnectedException, InterruptedException { 099 // build In-Band Bytestream request 100 InBandBytestreamRequest request = new ByteStreamRequest(this.manager, 101 (Open) streamInitiation); 102 103 // always accept the request 104 InBandBytestreamSession session = request.accept(); 105 session.setCloseBothStreamsEnabled(true); 106 return session.getInputStream(); 107 } 108 109 /** 110 * Derive from InBandBytestreamRequest to access protected constructor. 111 */ 112 private static final class ByteStreamRequest extends InBandBytestreamRequest { 113 114 private ByteStreamRequest(InBandBytestreamManager manager, Open byteStreamRequest) { 115 super(manager, byteStreamRequest); 116 } 117 118 } 119 120}