aboutsummaryrefslogtreecommitdiffstats
path: root/src/eu/siacs/conversations/xmpp/jingle/SocksConnection.java
blob: d4cb432a182dc075611aa3b75a6d53018abf02cf (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
package eu.siacs.conversations.xmpp.jingle;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
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 android.util.Log;

public class SocksConnection {

	private JingleConnection jingleConnection;
	private Socket socket;
	private String host;
	private String jid;
	private int port;
	private boolean isProxy = false;
	private String destination;
	private OutputStream outputStream;
	private boolean isEstablished = false;

	public SocksConnection(JingleConnection jingleConnection, String host,
			String jid, int port, String type) {
		this.jingleConnection = jingleConnection;
		this.host = host;
		this.jid = jid;
		this.port = port;
		this.isProxy = "proxy".equalsIgnoreCase(type);
		try {
			MessageDigest mDigest = MessageDigest.getInstance("SHA-1");
			StringBuilder destBuilder = new StringBuilder();
			destBuilder.append(jingleConnection.getSessionId());
			destBuilder.append(jingleConnection.getInitiator());
			destBuilder.append(jingleConnection.getResponder());
			mDigest.reset();
			this.destination = CryptoHelper.bytesToHex(mDigest
					.digest(destBuilder.toString().getBytes()));
		} catch (NoSuchAlgorithmException e) {

		}
	}

	public void connect(final OnSocksConnection callback) {
		new Thread(new Runnable() {
			
			@Override
			public void run() {
				try {
					socket = new Socket(host, port);
					InputStream is = socket.getInputStream();
					outputStream = socket.getOutputStream();
					byte[] login = { 0x05, 0x01, 0x00 };
					byte[] expectedReply = { 0x05, 0x00 };
					byte[] reply = new byte[2];
					outputStream.write(login);
					is.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];
						is.read(result);
						int status = result[1];
						if (status == 0) {
							Log.d("xmppService", "established connection with "+host + ":" + port
									+ "/" + destination);
							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 boolean isProxy() {
		return this.isProxy;
	}

	public String getJid() {
		return this.jid;
	}

	public void disconnect() {
		if (this.socket!=null) {
			try {
				this.socket.close();
				Log.d("xmppService","cloesd socket with "+this.host);
			} catch (IOException e) {
				Log.d("xmppService","error closing socket with "+this.host);
			}
		}
	}
	
	public boolean isEstablished() {
		return this.isEstablished;
	}
}