• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * $RCSfile$
3  * $Revision$
4  * $Date$
5  *
6  * Copyright 2003-2006 Jive Software.
7  *
8  * All rights reserved. Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  *     http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  */
20 package org.jivesoftware.smackx.filetransfer;
21 
22 import java.io.InputStream;
23 import java.io.OutputStream;
24 
25 import org.jivesoftware.smack.Connection;
26 import org.jivesoftware.smack.XMPPException;
27 import org.jivesoftware.smack.filter.AndFilter;
28 import org.jivesoftware.smack.filter.FromContainsFilter;
29 import org.jivesoftware.smack.filter.PacketFilter;
30 import org.jivesoftware.smack.filter.PacketTypeFilter;
31 import org.jivesoftware.smack.packet.IQ;
32 import org.jivesoftware.smack.packet.Packet;
33 import org.jivesoftware.smackx.bytestreams.ibb.InBandBytestreamManager;
34 import org.jivesoftware.smackx.bytestreams.ibb.InBandBytestreamRequest;
35 import org.jivesoftware.smackx.bytestreams.ibb.InBandBytestreamSession;
36 import org.jivesoftware.smackx.bytestreams.ibb.packet.Open;
37 import org.jivesoftware.smackx.packet.StreamInitiation;
38 
39 /**
40  * The In-Band Bytestream file transfer method, or IBB for short, transfers the
41  * file over the same XML Stream used by XMPP. It is the fall-back mechanism in
42  * case the SOCKS5 bytestream method of transferring files is not available.
43  *
44  * @author Alexander Wenckus
45  * @author Henning Staib
46  * @see <a href="http://xmpp.org/extensions/xep-0047.html">XEP-0047: In-Band
47  *      Bytestreams (IBB)</a>
48  */
49 public class IBBTransferNegotiator extends StreamNegotiator {
50 
51     private Connection connection;
52 
53     private InBandBytestreamManager manager;
54 
55     /**
56      * The default constructor for the In-Band Bytestream Negotiator.
57      *
58      * @param connection The connection which this negotiator works on.
59      */
IBBTransferNegotiator(Connection connection)60     protected IBBTransferNegotiator(Connection connection) {
61         this.connection = connection;
62         this.manager = InBandBytestreamManager.getByteStreamManager(connection);
63     }
64 
createOutgoingStream(String streamID, String initiator, String target)65     public OutputStream createOutgoingStream(String streamID, String initiator,
66                     String target) throws XMPPException {
67         InBandBytestreamSession session = this.manager.establishSession(target, streamID);
68         session.setCloseBothStreamsEnabled(true);
69         return session.getOutputStream();
70     }
71 
createIncomingStream(StreamInitiation initiation)72     public InputStream createIncomingStream(StreamInitiation initiation)
73                     throws XMPPException {
74         /*
75          * In-Band Bytestream initiation listener must ignore next in-band
76          * bytestream request with given session ID
77          */
78         this.manager.ignoreBytestreamRequestOnce(initiation.getSessionID());
79 
80         Packet streamInitiation = initiateIncomingStream(this.connection, initiation);
81         return negotiateIncomingStream(streamInitiation);
82     }
83 
getInitiationPacketFilter(String from, String streamID)84     public PacketFilter getInitiationPacketFilter(String from, String streamID) {
85         /*
86          * this method is always called prior to #negotiateIncomingStream() so
87          * the In-Band Bytestream initiation listener must ignore the next
88          * In-Band Bytestream request with the given session ID
89          */
90         this.manager.ignoreBytestreamRequestOnce(streamID);
91 
92         return new AndFilter(new FromContainsFilter(from), new IBBOpenSidFilter(streamID));
93     }
94 
getNamespaces()95     public String[] getNamespaces() {
96         return new String[] { InBandBytestreamManager.NAMESPACE };
97     }
98 
negotiateIncomingStream(Packet streamInitiation)99     InputStream negotiateIncomingStream(Packet streamInitiation) throws XMPPException {
100         // build In-Band Bytestream request
101         InBandBytestreamRequest request = new ByteStreamRequest(this.manager,
102                         (Open) streamInitiation);
103 
104         // always accept the request
105         InBandBytestreamSession session = request.accept();
106         session.setCloseBothStreamsEnabled(true);
107         return session.getInputStream();
108     }
109 
cleanup()110     public void cleanup() {
111     }
112 
113     /**
114      * This PacketFilter accepts an incoming In-Band Bytestream open request
115      * with a specified session ID.
116      */
117     private static class IBBOpenSidFilter extends PacketTypeFilter {
118 
119         private String sessionID;
120 
IBBOpenSidFilter(String sessionID)121         public IBBOpenSidFilter(String sessionID) {
122             super(Open.class);
123             if (sessionID == null) {
124                 throw new IllegalArgumentException("StreamID cannot be null");
125             }
126             this.sessionID = sessionID;
127         }
128 
accept(Packet packet)129         public boolean accept(Packet packet) {
130             if (super.accept(packet)) {
131                 Open bytestream = (Open) packet;
132 
133                 // packet must by of type SET and contains the given session ID
134                 return this.sessionID.equals(bytestream.getSessionID())
135                                 && IQ.Type.SET.equals(bytestream.getType());
136             }
137             return false;
138         }
139     }
140 
141     /**
142      * Derive from InBandBytestreamRequest to access protected constructor.
143      */
144     private static class ByteStreamRequest extends InBandBytestreamRequest {
145 
ByteStreamRequest(InBandBytestreamManager manager, Open byteStreamRequest)146         private ByteStreamRequest(InBandBytestreamManager manager, Open byteStreamRequest) {
147             super(manager, byteStreamRequest);
148         }
149 
150     }
151 
152 }
153