diff --git a/src/eu/siacs/conversations/xmpp/jingle/JingleConnection.java b/src/eu/siacs/conversations/xmpp/jingle/JingleConnection.java index f8083535..a5453443 100644 --- a/src/eu/siacs/conversations/xmpp/jingle/JingleConnection.java +++ b/src/eu/siacs/conversations/xmpp/jingle/JingleConnection.java @@ -1,5 +1,6 @@ package eu.siacs.conversations.xmpp.jingle; +import java.io.File; import java.util.ArrayList; import java.util.HashMap; import java.util.List; @@ -72,6 +73,8 @@ public class JingleConnection { status = STATUS_TERMINATED; } else if (packet.isAction("session-accept")) { accept(packet); + } else if (packet.isAction("transport-info")) { + transportInfo(packet); } else { Log.d("xmppService","packet arrived in connection. action was "+packet.getAction()); } @@ -135,11 +138,40 @@ public class JingleConnection { account.getXmppConnection().sendIqPacket(response, null); } + private void transportInfo(JinglePacket packet) { + Content content = packet.getJingleContent(); + Log.d("xmppService","transport info : "+content.toString()); + String cid = content.getUsedCandidate(); + if (cid!=null) { + final File file = this.mXmppConnectionService.getFileBackend().getImageFile(this.message); + final SocksConnection connection = this.connections.get(cid); + if (connection.isProxy()) { + IqPacket activation = new IqPacket(IqPacket.TYPE_SET); + activation.setTo(connection.getJid()); + activation.query("http://jabber.org/protocol/bytestreams").setAttribute("sid", this.getSessionId()); + activation.query().addChild("activate").setContent(this.getResponder()); + Log.d("xmppService","connection is proxy. need to activate "+activation.toString()); + this.account.getXmppConnection().sendIqPacket(activation, new OnIqPacketReceived() { + + @Override + public void onIqPacketReceived(Account account, IqPacket packet) { + Log.d("xmppService","activation result: "+packet.toString()); + connection.send(file); + } + }); + } else { + connection.send(file); + } + } + } + private void connectWithCandidates() { for(Element canditate : this.candidates) { String host = canditate.getAttribute("host"); int port = Integer.parseInt(canditate.getAttribute("port")); - SocksConnection socksConnection = new SocksConnection(this, host, port); + String type = canditate.getAttribute("type"); + String jid = canditate.getAttribute("jid"); + SocksConnection socksConnection = new SocksConnection(this, host, jid, port,type); socksConnection.connect(); this.connections.put(canditate.getAttribute("cid"), socksConnection); } diff --git a/src/eu/siacs/conversations/xmpp/jingle/JingleConnectionManager.java b/src/eu/siacs/conversations/xmpp/jingle/JingleConnectionManager.java index 7105774d..89ff717d 100644 --- a/src/eu/siacs/conversations/xmpp/jingle/JingleConnectionManager.java +++ b/src/eu/siacs/conversations/xmpp/jingle/JingleConnectionManager.java @@ -44,7 +44,6 @@ public class JingleConnectionManager { } public JingleConnection createNewConnection(Message message) { - Account account = message.getConversation().getAccount(); JingleConnection connection = new JingleConnection(this); connection.init(message); connections.add(connection); @@ -57,12 +56,6 @@ public class JingleConnectionManager { return connection; } - private String generateInternalId(String account, String counterpart, - String sid) { - return account + "#" + counterpart + "#" + sid; - - } - public XmppConnectionService getXmppConnectionService() { return this.xmppConnectionService; } diff --git a/src/eu/siacs/conversations/xmpp/jingle/SocksConnection.java b/src/eu/siacs/conversations/xmpp/jingle/SocksConnection.java index 5c36d66f..c1219ff7 100644 --- a/src/eu/siacs/conversations/xmpp/jingle/SocksConnection.java +++ b/src/eu/siacs/conversations/xmpp/jingle/SocksConnection.java @@ -1,5 +1,8 @@ package eu.siacs.conversations.xmpp.jingle; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; @@ -18,13 +21,18 @@ public class SocksConnection { private JingleConnection jingleConnection; private Socket socket; private String host; + private String jid; private int port; + private boolean isProxy = false; private String destination; + private OutputStream outputStream; - public SocksConnection(JingleConnection jingleConnection, String host, int port) { + public SocksConnection(JingleConnection jingleConnection, String host, String jid, int port, String type) { this.jingleConnection = jingleConnection; this.host = host; + this.jid = jid; this.port = port; + this.isProxy = "proxy".equalsIgnoreCase(type); try { MessageDigest mDigest = MessageDigest.getInstance("SHA-1"); StringBuilder destBuilder = new StringBuilder(); @@ -32,7 +40,6 @@ public class SocksConnection { destBuilder.append(jingleConnection.getInitiator()); destBuilder.append(jingleConnection.getResponder()); mDigest.reset(); - Log.d("xmppService","plain destination: "+destBuilder.toString()); this.destination = CryptoHelper.bytesToHex(mDigest.digest(destBuilder.toString().getBytes())); Log.d("xmppService","host="+host+", port="+port+", destination: "+destination); } catch (NoSuchAlgorithmException e) { @@ -44,15 +51,15 @@ public class SocksConnection { try { this.socket = new Socket(this.host, this.port); InputStream is = socket.getInputStream(); - OutputStream os = socket.getOutputStream(); + this.outputStream = socket.getOutputStream(); byte[] login = {0x05, 0x01, 0x00}; byte[] expectedReply = {0x05,0x00}; byte[] reply = new byte[2]; - os.write(login); + this.outputStream.write(login); is.read(reply); if (Arrays.equals(reply, expectedReply)) { String connect = ""+'\u0005'+'\u0001'+'\u0000'+'\u0003'+'\u0028'+this.destination+'\u0000'+'\u0000'; - os.write(connect.getBytes()); + this.outputStream.write(connect.getBytes()); byte[] result = new byte[2]; is.read(result); int status = result[0]; @@ -67,4 +74,40 @@ public class SocksConnection { return false; } } + + public void send(File file) { + FileInputStream fileInputStream = null; + try { + fileInputStream = new FileInputStream(file); + int count; + byte[] buffer = new byte[8192]; + while ((count = fileInputStream.read(buffer)) > 0) { + this.outputStream.write(buffer, 0, count); + } + + } catch (FileNotFoundException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } catch (IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } finally { + try { + if (fileInputStream!=null) { + fileInputStream.close(); + } + } catch (IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + } + + public boolean isProxy() { + return this.isProxy; + } + + public String getJid() { + return this.jid; + } } diff --git a/src/eu/siacs/conversations/xmpp/jingle/stanzas/Content.java b/src/eu/siacs/conversations/xmpp/jingle/stanzas/Content.java index 5ea4619f..27d6b9e3 100644 --- a/src/eu/siacs/conversations/xmpp/jingle/stanzas/Content.java +++ b/src/eu/siacs/conversations/xmpp/jingle/stanzas/Content.java @@ -43,4 +43,17 @@ public class Content extends Element { return transport.getChildren(); } } + + public String getUsedCandidate() { + Element transport = this.findChild("transport", "urn:xmpp:jingle:transports:s5b:1"); + if (transport==null) { + return null; + } + Element usedCandidate = transport.findChild("candidate-used"); + if (usedCandidate==null) { + return null; + } else { + return usedCandidate.getAttribute("cid"); + } + } }