1package eu.siacs.conversations.xmpp.jingle;
2
3import java.io.FileInputStream;
4import java.io.FileNotFoundException;
5import java.io.IOException;
6import java.io.InputStream;
7import java.io.OutputStream;
8import java.net.Socket;
9import java.net.UnknownHostException;
10import java.security.MessageDigest;
11import java.security.NoSuchAlgorithmException;
12import java.util.Arrays;
13
14import eu.siacs.conversations.utils.CryptoHelper;
15
16import android.util.Log;
17
18public class SocksConnection {
19
20 private JingleConnection jingleConnection;
21 private Socket socket;
22 private String host;
23 private String jid;
24 private int port;
25 private boolean isProxy = false;
26 private String destination;
27 private OutputStream outputStream;
28 private boolean isEstablished = false;
29
30 public SocksConnection(JingleConnection jingleConnection, String host,
31 String jid, int port, String type) {
32 this.jingleConnection = jingleConnection;
33 this.host = host;
34 this.jid = jid;
35 this.port = port;
36 this.isProxy = "proxy".equalsIgnoreCase(type);
37 try {
38 MessageDigest mDigest = MessageDigest.getInstance("SHA-1");
39 StringBuilder destBuilder = new StringBuilder();
40 destBuilder.append(jingleConnection.getSessionId());
41 destBuilder.append(jingleConnection.getInitiator());
42 destBuilder.append(jingleConnection.getResponder());
43 mDigest.reset();
44 this.destination = CryptoHelper.bytesToHex(mDigest
45 .digest(destBuilder.toString().getBytes()));
46 } catch (NoSuchAlgorithmException e) {
47
48 }
49 }
50
51 public void connect(final OnSocksConnection callback) {
52 new Thread(new Runnable() {
53
54 @Override
55 public void run() {
56 try {
57 socket = new Socket(host, port);
58 InputStream is = socket.getInputStream();
59 outputStream = socket.getOutputStream();
60 byte[] login = { 0x05, 0x01, 0x00 };
61 byte[] expectedReply = { 0x05, 0x00 };
62 byte[] reply = new byte[2];
63 outputStream.write(login);
64 is.read(reply);
65 if (Arrays.equals(reply, expectedReply)) {
66 String connect = "" + '\u0005' + '\u0001' + '\u0000' + '\u0003'
67 + '\u0028' + destination + '\u0000' + '\u0000';
68 outputStream.write(connect.getBytes());
69 byte[] result = new byte[2];
70 is.read(result);
71 int status = result[1];
72 if (status == 0) {
73 Log.d("xmppService", "established connection with "+host + ":" + port
74 + "/" + destination);
75 isEstablished = true;
76 callback.established();
77 } else {
78 callback.failed();
79 }
80 } else {
81 socket.close();
82 callback.failed();
83 }
84 } catch (UnknownHostException e) {
85 callback.failed();
86 } catch (IOException e) {
87 callback.failed();
88 }
89 }
90 }).start();
91
92 }
93
94 public void send(final JingleFile file, final OnFileTransmitted callback) {
95 new Thread(new Runnable() {
96
97 @Override
98 public void run() {
99 FileInputStream fileInputStream = null;
100 try {
101 MessageDigest digest = MessageDigest.getInstance("SHA-1");
102 digest.reset();
103 fileInputStream = new FileInputStream(file);
104 int count;
105 byte[] buffer = new byte[8192];
106 while ((count = fileInputStream.read(buffer)) > 0) {
107 outputStream.write(buffer, 0, count);
108 digest.update(buffer, 0, count);
109 }
110 outputStream.flush();
111 file.setSha1Sum(CryptoHelper.bytesToHex(digest.digest()));
112 if (callback!=null) {
113 callback.onFileTransmitted(file);
114 }
115 } catch (FileNotFoundException e) {
116 // TODO Auto-generated catch block
117 e.printStackTrace();
118 } catch (IOException e) {
119 // TODO Auto-generated catch block
120 e.printStackTrace();
121 } catch (NoSuchAlgorithmException e) {
122 // TODO Auto-generated catch block
123 e.printStackTrace();
124 } finally {
125 try {
126 if (fileInputStream != null) {
127 fileInputStream.close();
128 }
129 } catch (IOException e) {
130 // TODO Auto-generated catch block
131 e.printStackTrace();
132 }
133 }
134 }
135 }).start();
136
137 }
138
139 public boolean isProxy() {
140 return this.isProxy;
141 }
142
143 public String getJid() {
144 return this.jid;
145 }
146
147 public void disconnect() {
148 if (this.socket!=null) {
149 try {
150 this.socket.close();
151 Log.d("xmppService","cloesd socket with "+this.host);
152 } catch (IOException e) {
153 Log.d("xmppService","error closing socket with "+this.host);
154 }
155 }
156 }
157
158 public boolean isEstablished() {
159 return this.isEstablished;
160 }
161}