diff options
Diffstat (limited to 'src/eu/siacs/conversations/xmpp/jingle/JingleSocks5Transport.java')
-rw-r--r-- | src/eu/siacs/conversations/xmpp/jingle/JingleSocks5Transport.java | 206 |
1 files changed, 206 insertions, 0 deletions
diff --git a/src/eu/siacs/conversations/xmpp/jingle/JingleSocks5Transport.java b/src/eu/siacs/conversations/xmpp/jingle/JingleSocks5Transport.java new file mode 100644 index 00000000..f37d5a71 --- /dev/null +++ b/src/eu/siacs/conversations/xmpp/jingle/JingleSocks5Transport.java @@ -0,0 +1,206 @@ +package eu.siacs.conversations.xmpp.jingle; + +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.Socket; +import java.net.UnknownHostException; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.util.Arrays; + +import eu.siacs.conversations.utils.CryptoHelper; +import eu.siacs.conversations.xml.Element; + +import android.util.Log; +import android.widget.Button; + +public class JingleSocks5Transport extends JingleTransport { + private JingleCandidate candidate; + private String destination; + private OutputStream outputStream; + private InputStream inputStream; + private boolean isEstablished = false; + protected Socket socket; + + public JingleSocks5Transport(JingleConnection jingleConnection, JingleCandidate candidate) { + this.candidate = candidate; + try { + MessageDigest mDigest = MessageDigest.getInstance("SHA-1"); + StringBuilder destBuilder = new StringBuilder(); + destBuilder.append(jingleConnection.getSessionId()); + if (candidate.isOurs()) { + destBuilder.append(jingleConnection.getAccountJid()); + destBuilder.append(jingleConnection.getCounterPart()); + } else { + destBuilder.append(jingleConnection.getCounterPart()); + destBuilder.append(jingleConnection.getAccountJid()); + } + mDigest.reset(); + this.destination = CryptoHelper.bytesToHex(mDigest + .digest(destBuilder.toString().getBytes())); + } catch (NoSuchAlgorithmException e) { + + } + } + + public void connect(final OnTransportConnected callback) { + new Thread(new Runnable() { + + @Override + public void run() { + try { + socket = new Socket(candidate.getHost(), candidate.getPort()); + inputStream = socket.getInputStream(); + outputStream = socket.getOutputStream(); + byte[] login = { 0x05, 0x01, 0x00 }; + byte[] expectedReply = { 0x05, 0x00 }; + byte[] reply = new byte[2]; + outputStream.write(login); + inputStream.read(reply); + if (Arrays.equals(reply, expectedReply)) { + String connect = "" + '\u0005' + '\u0001' + '\u0000' + '\u0003' + + '\u0028' + destination + '\u0000' + '\u0000'; + outputStream.write(connect.getBytes()); + byte[] result = new byte[2]; + inputStream.read(result); + int status = result[1]; + if (status == 0) { + isEstablished = true; + callback.established(); + } else { + callback.failed(); + } + } else { + socket.close(); + callback.failed(); + } + } catch (UnknownHostException e) { + callback.failed(); + } catch (IOException e) { + callback.failed(); + } + } + }).start(); + + } + + public void send(final JingleFile file, final OnFileTransmitted callback) { + new Thread(new Runnable() { + + @Override + public void run() { + FileInputStream fileInputStream = null; + try { + MessageDigest digest = MessageDigest.getInstance("SHA-1"); + digest.reset(); + fileInputStream = new FileInputStream(file); + int count; + byte[] buffer = new byte[8192]; + while ((count = fileInputStream.read(buffer)) > 0) { + outputStream.write(buffer, 0, count); + digest.update(buffer, 0, count); + } + outputStream.flush(); + file.setSha1Sum(CryptoHelper.bytesToHex(digest.digest())); + if (callback!=null) { + callback.onFileTransmitted(file); + } + } catch (FileNotFoundException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } catch (IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } catch (NoSuchAlgorithmException 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(); + } + } + } + }).start(); + + } + + public void receive(final JingleFile file, final OnFileTransmitted callback) { + new Thread(new Runnable() { + + @Override + public void run() { + try { + MessageDigest digest = MessageDigest.getInstance("SHA-1"); + digest.reset(); + inputStream.skip(45); + file.getParentFile().mkdirs(); + file.createNewFile(); + FileOutputStream fileOutputStream = new FileOutputStream(file); + long remainingSize = file.getExpectedSize(); + byte[] buffer = new byte[8192]; + int count = buffer.length; + while(remainingSize > 0) { + Log.d("xmppService","remaning size:"+remainingSize); + if (remainingSize<=count) { + count = (int) remainingSize; + } + count = inputStream.read(buffer, 0, count); + if (count==-1) { + Log.d("xmppService","end of stream"); + } else { + fileOutputStream.write(buffer, 0, count); + digest.update(buffer, 0, count); + remainingSize-=count; + } + } + fileOutputStream.flush(); + fileOutputStream.close(); + file.setSha1Sum(CryptoHelper.bytesToHex(digest.digest())); + Log.d("xmppService","transmitted filename was: "+file.getAbsolutePath()); + callback.onFileTransmitted(file); + } catch (FileNotFoundException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } catch (IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } catch (NoSuchAlgorithmException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + }).start(); + } + + public boolean isProxy() { + return this.candidate.getType() == JingleCandidate.TYPE_PROXY; + } + + public void disconnect() { + if (this.socket!=null) { + try { + this.socket.close(); + Log.d("xmppService","cloesd socket with "+candidate.getHost()+":"+candidate.getPort()); + } catch (IOException e) { + Log.d("xmppService","error closing socket with "+candidate.getHost()+":"+candidate.getPort()); + } + } + } + + public boolean isEstablished() { + return this.isEstablished; + } + + public JingleCandidate getCandidate() { + return this.candidate; + } +} |