JingleConnection.java

  1package eu.siacs.conversations.xmpp.jingle;
  2
  3import java.util.ArrayList;
  4import java.util.HashMap;
  5import java.util.List;
  6
  7import android.util.Log;
  8
  9import eu.siacs.conversations.entities.Account;
 10import eu.siacs.conversations.entities.Message;
 11import eu.siacs.conversations.services.XmppConnectionService;
 12import eu.siacs.conversations.xml.Element;
 13import eu.siacs.conversations.xmpp.OnIqPacketReceived;
 14import eu.siacs.conversations.xmpp.jingle.stanzas.Content;
 15import eu.siacs.conversations.xmpp.jingle.stanzas.JinglePacket;
 16import eu.siacs.conversations.xmpp.stanzas.IqPacket;
 17
 18public class JingleConnection {
 19
 20	private JingleConnectionManager mJingleConnectionManager;
 21	private XmppConnectionService mXmppConnectionService;
 22	
 23	public static final int STATUS_INITIATED = 0;
 24	public static final int STATUS_ACCEPTED = 1;
 25	public static final int STATUS_TERMINATED = 2;
 26	public static final int STATUS_FAILED = 99;
 27	
 28	private int status = -1;
 29	private Message message;
 30	private String sessionId;
 31	private Account account;
 32	private String initiator;
 33	private String responder;
 34	private List<Element> candidates = new ArrayList<Element>();
 35	private HashMap<String, SocksConnection> connections = new HashMap<String, SocksConnection>();
 36	
 37	private OnIqPacketReceived responseListener = new OnIqPacketReceived() {
 38		
 39		@Override
 40		public void onIqPacketReceived(Account account, IqPacket packet) {
 41			if (packet.getType() == IqPacket.TYPE_ERROR) {
 42				mXmppConnectionService.markMessage(message, Message.STATUS_SEND_FAILED);
 43				status = STATUS_FAILED;
 44			}
 45		}
 46	};
 47	
 48	public JingleConnection(JingleConnectionManager mJingleConnectionManager) {
 49		this.mJingleConnectionManager = mJingleConnectionManager;
 50		this.mXmppConnectionService = mJingleConnectionManager.getXmppConnectionService();
 51		this.sessionId = this.mJingleConnectionManager.nextRandomId();
 52	}
 53	
 54	public String getSessionId() {
 55		return this.sessionId;
 56	}
 57	
 58	public String getAccountJid() {
 59		return this.account.getJid();
 60	}
 61	
 62	public String getCounterPart() {
 63		return this.message.getCounterpart();
 64	}
 65	
 66	public void deliverPacket(JinglePacket packet) {
 67		
 68		if (packet.isAction("session-terminate")) {
 69			if (status == STATUS_INITIATED) {
 70				mXmppConnectionService.markMessage(message, Message.STATUS_SEND_REJECTED);
 71			}
 72			status = STATUS_TERMINATED;
 73		} else if (packet.isAction("session-accept")) {
 74			accept(packet);
 75		} else {
 76			Log.d("xmppService","packet arrived in connection. action was "+packet.getAction());
 77		}
 78	}
 79	
 80	public void init(Message message) {
 81		this.message = message;
 82		this.account = message.getConversation().getAccount();
 83		this.initiator = this.account.getFullJid();
 84		this.responder = this.message.getCounterpart();
 85		if (this.candidates.size() > 0) {
 86			this.sendInitRequest();
 87		} else {
 88			this.mJingleConnectionManager.getPrimaryCandidate(account, new OnPrimaryCandidateFound() {
 89				
 90				@Override
 91				public void onPrimaryCandidateFound(boolean success, Element canditate) {
 92					if (success) {
 93						candidates.add(canditate);
 94					}
 95					sendInitRequest();
 96				}
 97			});
 98		}
 99		
100	}
101	
102	private void sendInitRequest() {
103		JinglePacket packet = this.bootstrapPacket();
104		packet.setAction("session-initiate");
105		packet.setInitiator(this.account.getFullJid());
106		Content content = new Content();
107		if (message.getType() == Message.TYPE_IMAGE) {
108			content.setAttribute("creator", "initiator");
109			content.setAttribute("name", "a-file-offer");
110			content.offerFile(this.mXmppConnectionService.getFileBackend().getImageFile(message));
111			content.setCandidates(this.mJingleConnectionManager.nextRandomId(),this.candidates);
112			packet.setContent(content);
113			Log.d("xmppService",packet.toString());
114			account.getXmppConnection().sendIqPacket(packet, this.responseListener);
115			this.status = STATUS_INITIATED;
116		}
117	}
118	
119	private JinglePacket bootstrapPacket() {
120		JinglePacket packet = new JinglePacket();
121		packet.setFrom(account.getFullJid());
122		packet.setTo(this.message.getCounterpart()); //fixme, not right in all cases;
123		packet.setSessionId(this.sessionId);
124		return packet;
125	}
126	
127	private void accept(JinglePacket packet) {
128		Log.d("xmppService","session-accept: "+packet.toString());
129		Content content = packet.getJingleContent();
130		this.candidates.addAll(content.getCanditates());
131		this.status = STATUS_ACCEPTED;
132		this.connectWithCandidates();
133		IqPacket response = packet.generateRespone(IqPacket.TYPE_RESULT);
134		Log.d("xmppService","response "+response.toString());
135		account.getXmppConnection().sendIqPacket(response, null);
136	}
137	
138	private void connectWithCandidates() {
139		for(Element canditate : this.candidates) {
140			String host = canditate.getAttribute("host");
141			int port = Integer.parseInt(canditate.getAttribute("port"));
142			SocksConnection socksConnection = new SocksConnection(this, host, port);
143			socksConnection.connect();
144			this.connections.put(canditate.getAttribute("cid"), socksConnection);
145		}
146	}
147	
148	private void sendCandidateUsed(String cid) {
149		
150	}
151
152	public String getInitiator() {
153		return this.initiator;
154	}
155	
156	public String getResponder() {
157		return this.responder;
158	}
159}