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) {
 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			destBuilder.append(jingleConnection.getInitiator());
 45			destBuilder.append(jingleConnection.getResponder());
 46			mDigest.reset();
 47			this.destination = CryptoHelper.bytesToHex(mDigest
 48					.digest(destBuilder.toString().getBytes()));
 49		} catch (NoSuchAlgorithmException e) {
 50
 51		}
 52	}
 53
 54	public void connect(final OnSocksConnection callback) {
 55		new Thread(new Runnable() {
 56			
 57			@Override
 58			public void run() {
 59				try {
 60					socket = new Socket(host, port);
 61					inputStream = socket.getInputStream();
 62					outputStream = socket.getOutputStream();
 63					byte[] login = { 0x05, 0x01, 0x00 };
 64					byte[] expectedReply = { 0x05, 0x00 };
 65					byte[] reply = new byte[2];
 66					outputStream.write(login);
 67					inputStream.read(reply);
 68					if (Arrays.equals(reply, expectedReply)) {
 69						String connect = "" + '\u0005' + '\u0001' + '\u0000' + '\u0003'
 70								+ '\u0028' + destination + '\u0000' + '\u0000';
 71						outputStream.write(connect.getBytes());
 72						byte[] result = new byte[2];
 73						inputStream.read(result);
 74						int status = result[1];
 75						if (status == 0) {
 76							Log.d("xmppService", "established connection with "+host + ":" + port
 77									+ "/" + destination);
 78							isEstablished = true;
 79							callback.established();
 80						} else {
 81							callback.failed();
 82						}
 83					} else {
 84						socket.close();
 85						callback.failed();
 86					}
 87				} catch (UnknownHostException e) {
 88					callback.failed();
 89				} catch (IOException e) {
 90					callback.failed();
 91				}
 92			}
 93		}).start();
 94		
 95	}
 96
 97	public void send(final JingleFile file, final OnFileTransmitted callback) {
 98		new Thread(new Runnable() {
 99			
100			@Override
101			public void run() {
102				FileInputStream fileInputStream = null;
103				try {
104					MessageDigest digest = MessageDigest.getInstance("SHA-1");
105					digest.reset();
106					fileInputStream = new FileInputStream(file);
107					int count;
108					byte[] buffer = new byte[8192];
109					while ((count = fileInputStream.read(buffer)) > 0) {
110						outputStream.write(buffer, 0, count);
111						digest.update(buffer, 0, count);
112					}
113					outputStream.flush();
114					file.setSha1Sum(CryptoHelper.bytesToHex(digest.digest()));
115					if (callback!=null) {
116						callback.onFileTransmitted(file);
117					}
118				} catch (FileNotFoundException e) {
119					// TODO Auto-generated catch block
120					e.printStackTrace();
121				} catch (IOException e) {
122					// TODO Auto-generated catch block
123					e.printStackTrace();
124				} catch (NoSuchAlgorithmException e) {
125					// TODO Auto-generated catch block
126					e.printStackTrace();
127				} finally {
128					try {
129						if (fileInputStream != null) {
130							fileInputStream.close();
131						}
132					} catch (IOException e) {
133						// TODO Auto-generated catch block
134						e.printStackTrace();
135					}
136				}
137			}
138		}).start();
139		
140	}
141	
142	public void receive(final JingleFile file, final OnFileTransmitted callback) {
143		new Thread(new Runnable() {
144			
145			@Override
146			public void run() {
147				try {
148					MessageDigest digest = MessageDigest.getInstance("SHA-1");
149					digest.reset();
150					inputStream.skip(45);
151					file.getParentFile().mkdirs();
152					file.createNewFile();
153					FileOutputStream fileOutputStream = new FileOutputStream(file);
154					long remainingSize = file.getExpectedSize();
155					byte[] buffer = new byte[8192];
156					int count = buffer.length;
157					while(remainingSize > 0) {
158						Log.d("xmppService","remaning size:"+remainingSize);
159						if (remainingSize<=count) {
160							count = (int) remainingSize;
161						}
162						count = inputStream.read(buffer, 0, count);
163						if (count==-1) {
164							Log.d("xmppService","end of stream");
165						} else {
166							fileOutputStream.write(buffer, 0, count);
167							digest.update(buffer, 0, count);
168							remainingSize-=count;
169						}
170					}
171					fileOutputStream.flush();
172					fileOutputStream.close();
173					file.setSha1Sum(CryptoHelper.bytesToHex(digest.digest()));
174					Log.d("xmppService","transmitted filename was: "+file.getAbsolutePath());
175					callback.onFileTransmitted(file);
176				} catch (FileNotFoundException e) {
177					// TODO Auto-generated catch block
178					e.printStackTrace();
179				} catch (IOException e) {
180					// TODO Auto-generated catch block
181					e.printStackTrace();
182				} catch (NoSuchAlgorithmException e) {
183					// TODO Auto-generated catch block
184					e.printStackTrace();
185				}
186			}
187		}).start();
188	}
189
190	public boolean isProxy() {
191		return this.isProxy;
192	}
193
194	public String getJid() {
195		return this.jid;
196	}
197	
198	public String getCid() {
199		return this.cid;
200	}
201
202	public void disconnect() {
203		if (this.socket!=null) {
204			try {
205				this.socket.close();
206				Log.d("xmppService","cloesd socket with "+this.host);
207			} catch (IOException e) {
208				Log.d("xmppService","error closing socket with "+this.host);
209			}
210		}
211	}
212	
213	public boolean isEstablished() {
214		return this.isEstablished;
215	}
216}