JingleConnectionManager.java

  1package eu.siacs.conversations.xmpp.jingle;
  2
  3import java.math.BigInteger;
  4import java.security.SecureRandom;
  5import java.util.HashMap;
  6import java.util.List;
  7import java.util.concurrent.CopyOnWriteArrayList;
  8import android.annotation.SuppressLint;
  9import android.util.Log;
 10import eu.siacs.conversations.entities.Account;
 11import eu.siacs.conversations.entities.Message;
 12import eu.siacs.conversations.services.XmppConnectionService;
 13import eu.siacs.conversations.xml.Element;
 14import eu.siacs.conversations.xmpp.OnIqPacketReceived;
 15import eu.siacs.conversations.xmpp.jingle.stanzas.JinglePacket;
 16import eu.siacs.conversations.xmpp.stanzas.IqPacket;
 17
 18public class JingleConnectionManager {
 19
 20	private XmppConnectionService xmppConnectionService;
 21
 22	private List<JingleConnection> connections = new CopyOnWriteArrayList<JingleConnection>();
 23
 24	private HashMap<String, JingleCandidate> primaryCandidates = new HashMap<String, JingleCandidate>();
 25
 26	@SuppressLint("TrulyRandom")
 27	private SecureRandom random = new SecureRandom();
 28
 29	public JingleConnectionManager(XmppConnectionService service) {
 30		this.xmppConnectionService = service;
 31	}
 32
 33	public void deliverPacket(Account account, JinglePacket packet) {
 34		if (packet.isAction("session-initiate")) {
 35			JingleConnection connection = new JingleConnection(this);
 36			connection.init(account,packet);
 37			connections.add(connection);
 38		} else {
 39			for (JingleConnection connection : connections) {
 40				if (connection.getAccountJid().equals(account.getFullJid()) && connection
 41						.getSessionId().equals(packet.getSessionId()) && connection
 42						.getCounterPart().equals(packet.getFrom())) {
 43					connection.deliverPacket(packet);
 44					return;
 45				}
 46			}
 47			account.getXmppConnection().sendIqPacket(packet.generateRespone(IqPacket.TYPE_ERROR), null);
 48		}
 49	}
 50
 51	public JingleConnection createNewConnection(Message message) {
 52		JingleConnection connection = new JingleConnection(this);
 53		connection.init(message);
 54		this.connections.add(connection);
 55		return connection;
 56	}
 57
 58	public JingleConnection createNewConnection(JinglePacket packet) {
 59		JingleConnection connection = new JingleConnection(this);
 60		this.connections.add(connection);
 61		return connection;
 62	}
 63	
 64	public void finishConnection(JingleConnection connection) {
 65		this.connections.remove(connection);
 66	}
 67
 68	public XmppConnectionService getXmppConnectionService() {
 69		return this.xmppConnectionService;
 70	}
 71
 72	public void getPrimaryCandidate(Account account,
 73			final OnPrimaryCandidateFound listener) {
 74		if (!this.primaryCandidates.containsKey(account.getJid())) {
 75			String xmlns = "http://jabber.org/protocol/bytestreams";
 76			final String proxy = account.getXmppConnection()
 77					.findDiscoItemByFeature(xmlns);
 78			if (proxy != null) {
 79				IqPacket iq = new IqPacket(IqPacket.TYPE_GET);
 80				iq.setTo(proxy);
 81				iq.query(xmlns);
 82				account.getXmppConnection().sendIqPacket(iq,
 83						new OnIqPacketReceived() {
 84
 85							@Override
 86							public void onIqPacketReceived(Account account,
 87									IqPacket packet) {
 88								Element streamhost = packet
 89										.query()
 90										.findChild("streamhost",
 91												"http://jabber.org/protocol/bytestreams");
 92								if (streamhost != null) {
 93									JingleCandidate candidate = new JingleCandidate(nextRandomId(),true);
 94									candidate.setHost(streamhost.getAttribute("host"));
 95									candidate.setPort(Integer.parseInt(streamhost.getAttribute("port")));
 96									candidate.setType(JingleCandidate.TYPE_PROXY);
 97									candidate.setJid(proxy);
 98									candidate.setPriority(655360+65535);
 99									primaryCandidates.put(account.getJid(),
100											candidate);
101									listener.onPrimaryCandidateFound(true,
102											candidate);
103								} else {
104									listener.onPrimaryCandidateFound(false,
105											null);
106								}
107							}
108						});
109			} else {
110				listener.onPrimaryCandidateFound(false, null);
111			}
112
113		} else {
114			listener.onPrimaryCandidateFound(true,
115					this.primaryCandidates.get(account.getJid()));
116		}
117	}
118
119	public String nextRandomId() {
120		return new BigInteger(50, random).toString(32);
121	}
122	
123	public long getAutoAcceptFileSize() {
124		String config = this.xmppConnectionService.getPreferences().getString("auto_accept_file_size", "524288");
125		try {
126			return Long.parseLong(config);
127		} catch (NumberFormatException e) {
128			return 524288;
129		}
130	}
131
132	public void deliverIbbPacket(Account account, IqPacket packet) {
133		String sid = null;
134		Element payload = null;
135		if (packet.hasChild("open","http://jabber.org/protocol/ibb")) {
136			payload = packet.findChild("open","http://jabber.org/protocol/ibb");
137			sid = payload.getAttribute("sid");
138		} else if (packet.hasChild("data","http://jabber.org/protocol/ibb")) {
139			payload = packet.findChild("data","http://jabber.org/protocol/ibb");
140			sid = payload.getAttribute("sid");
141		}
142		if (sid!=null) {
143			for (JingleConnection connection : connections) {
144				if (connection.hasTransportId(sid)) {
145					JingleTransport transport = connection.getTransport();
146					if (transport instanceof JingleInbandTransport) {
147						JingleInbandTransport inbandTransport = (JingleInbandTransport) transport;
148						inbandTransport.deliverPayload(packet,payload);
149						return;
150					}
151				}
152			}
153			Log.d("xmppService","couldnt deliver payload: "+payload.toString());
154		} else {
155			Log.d("xmppService","no sid found in incomming ibb packet");
156		}
157	}
158	
159	public void cancelInTransmission() {
160		for(JingleConnection connection : this.connections) {
161			if (connection.getStatus() == JingleConnection.STATUS_TRANSMITTING) {
162				connection.cancel();
163			}
164		}
165	}
166}