SocksConnection.java

  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}