1package eu.siacs.conversations.xmpp.jingle;
2
3import java.io.FileInputStream;
4import java.io.FileNotFoundException;
5import java.io.FileOutputStream;
6import java.io.IOException;
7import java.io.InputStream;
8import java.io.OutputStream;
9import java.net.Socket;
10import java.net.UnknownHostException;
11import java.security.MessageDigest;
12import java.security.NoSuchAlgorithmException;
13import java.util.Arrays;
14
15import eu.siacs.conversations.utils.CryptoHelper;
16import eu.siacs.conversations.xml.Element;
17
18import android.util.Log;
19import android.widget.Button;
20
21public class SocksConnection {
22 private Socket socket;
23 private String host;
24 private String jid;
25 private String cid;
26 private int port;
27 private boolean isProxy = false;
28 private String destination;
29 private OutputStream outputStream;
30 private InputStream inputStream;
31 private boolean isEstablished = false;
32
33 public SocksConnection(JingleConnection jingleConnection, Element candidate, boolean initating) {
34 this.cid = candidate.getAttribute("cid");
35 this.host = candidate.getAttribute("host");
36 this.port = Integer.parseInt(candidate.getAttribute("port"));
37 String type = candidate.getAttribute("type");
38 this.jid = candidate.getAttribute("jid");
39 this.isProxy = "proxy".equalsIgnoreCase(type);
40 try {
41 MessageDigest mDigest = MessageDigest.getInstance("SHA-1");
42 StringBuilder destBuilder = new StringBuilder();
43 destBuilder.append(jingleConnection.getSessionId());
44 if (initating) {
45 destBuilder.append(jingleConnection.getAccountJid());
46 destBuilder.append(jingleConnection.getCounterPart());
47 } else {
48 destBuilder.append(jingleConnection.getCounterPart());
49 destBuilder.append(jingleConnection.getAccountJid());
50 }
51 mDigest.reset();
52 this.destination = CryptoHelper.bytesToHex(mDigest
53 .digest(destBuilder.toString().getBytes()));
54 } catch (NoSuchAlgorithmException e) {
55
56 }
57 }
58
59 public void connect(final OnSocksConnection callback) {
60 new Thread(new Runnable() {
61
62 @Override
63 public void run() {
64 try {
65 socket = new Socket(host, port);
66 inputStream = socket.getInputStream();
67 outputStream = socket.getOutputStream();
68 byte[] login = { 0x05, 0x01, 0x00 };
69 byte[] expectedReply = { 0x05, 0x00 };
70 byte[] reply = new byte[2];
71 outputStream.write(login);
72 inputStream.read(reply);
73 if (Arrays.equals(reply, expectedReply)) {
74 String connect = "" + '\u0005' + '\u0001' + '\u0000' + '\u0003'
75 + '\u0028' + destination + '\u0000' + '\u0000';
76 outputStream.write(connect.getBytes());
77 byte[] result = new byte[2];
78 inputStream.read(result);
79 int status = result[1];
80 if (status == 0) {
81 Log.d("xmppService", "established connection with "+host + ":" + port
82 + "/" + destination);
83 isEstablished = true;
84 callback.established();
85 } else {
86 callback.failed();
87 }
88 } else {
89 socket.close();
90 callback.failed();
91 }
92 } catch (UnknownHostException e) {
93 callback.failed();
94 } catch (IOException e) {
95 callback.failed();
96 }
97 }
98 }).start();
99
100 }
101
102 public void send(final JingleFile file, final OnFileTransmitted callback) {
103 new Thread(new Runnable() {
104
105 @Override
106 public void run() {
107 FileInputStream fileInputStream = null;
108 try {
109 MessageDigest digest = MessageDigest.getInstance("SHA-1");
110 digest.reset();
111 fileInputStream = new FileInputStream(file);
112 int count;
113 byte[] buffer = new byte[8192];
114 while ((count = fileInputStream.read(buffer)) > 0) {
115 outputStream.write(buffer, 0, count);
116 digest.update(buffer, 0, count);
117 }
118 outputStream.flush();
119 file.setSha1Sum(CryptoHelper.bytesToHex(digest.digest()));
120 if (callback!=null) {
121 callback.onFileTransmitted(file);
122 }
123 } catch (FileNotFoundException e) {
124 // TODO Auto-generated catch block
125 e.printStackTrace();
126 } catch (IOException e) {
127 // TODO Auto-generated catch block
128 e.printStackTrace();
129 } catch (NoSuchAlgorithmException e) {
130 // TODO Auto-generated catch block
131 e.printStackTrace();
132 } finally {
133 try {
134 if (fileInputStream != null) {
135 fileInputStream.close();
136 }
137 } catch (IOException e) {
138 // TODO Auto-generated catch block
139 e.printStackTrace();
140 }
141 }
142 }
143 }).start();
144
145 }
146
147 public void receive(final JingleFile file, final OnFileTransmitted callback) {
148 new Thread(new Runnable() {
149
150 @Override
151 public void run() {
152 try {
153 MessageDigest digest = MessageDigest.getInstance("SHA-1");
154 digest.reset();
155 inputStream.skip(45);
156 file.getParentFile().mkdirs();
157 file.createNewFile();
158 FileOutputStream fileOutputStream = new FileOutputStream(file);
159 long remainingSize = file.getExpectedSize();
160 byte[] buffer = new byte[8192];
161 int count = buffer.length;
162 while(remainingSize > 0) {
163 Log.d("xmppService","remaning size:"+remainingSize);
164 if (remainingSize<=count) {
165 count = (int) remainingSize;
166 }
167 count = inputStream.read(buffer, 0, count);
168 if (count==-1) {
169 Log.d("xmppService","end of stream");
170 } else {
171 fileOutputStream.write(buffer, 0, count);
172 digest.update(buffer, 0, count);
173 remainingSize-=count;
174 }
175 }
176 fileOutputStream.flush();
177 fileOutputStream.close();
178 file.setSha1Sum(CryptoHelper.bytesToHex(digest.digest()));
179 Log.d("xmppService","transmitted filename was: "+file.getAbsolutePath());
180 callback.onFileTransmitted(file);
181 } catch (FileNotFoundException e) {
182 // TODO Auto-generated catch block
183 e.printStackTrace();
184 } catch (IOException e) {
185 // TODO Auto-generated catch block
186 e.printStackTrace();
187 } catch (NoSuchAlgorithmException e) {
188 // TODO Auto-generated catch block
189 e.printStackTrace();
190 }
191 }
192 }).start();
193 }
194
195 public boolean isProxy() {
196 return this.isProxy;
197 }
198
199 public String getJid() {
200 return this.jid;
201 }
202
203 public String getCid() {
204 return this.cid;
205 }
206
207 public void disconnect() {
208 if (this.socket!=null) {
209 try {
210 this.socket.close();
211 Log.d("xmppService","cloesd socket with "+this.host);
212 } catch (IOException e) {
213 Log.d("xmppService","error closing socket with "+this.host);
214 }
215 }
216 }
217
218 public boolean isEstablished() {
219 return this.isEstablished;
220 }
221}