1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.xnap.plugin.opennap.net;
21
22 import java.io.BufferedInputStream;
23 import java.io.FileInputStream;
24 import java.io.IOException;
25 import java.io.InputStream;
26 import java.io.OutputStream;
27 import java.net.Socket;
28
29 import org.apache.log4j.Logger;
30 import org.xnap.XNap;
31 import org.xnap.io.ThrottledOutputStream;
32 import org.xnap.net.NetHelper;
33 import org.xnap.plugin.opennap.net.msg.MessageHandler;
34 import org.xnap.plugin.opennap.net.msg.client.DownloadCompleteMessage;
35 import org.xnap.plugin.opennap.net.msg.client.DownloadingFileMessage;
36 import org.xnap.plugin.opennap.user.OpenNapUser;
37 import org.xnap.util.State;
38
39 /***
40 * Uploads a file.
41 */
42 public class OpenNapUploadRunner implements Runnable {
43
44
45
46 /***
47 * Socket timeout during connect.
48 */
49 public static final int CONNECT_TIMEOUT = 1 * 60 * 1000;
50
51 /***
52 * Abort transfer if stalled for this long.
53 */
54 public static final int TRANSFER_TIMEOUT = 2 * 60 * 1000;
55
56
57
58 private static Logger logger = Logger.getLogger(OpenNapUploadRunner.class);
59
60 private OpenNapUpload parent;
61 private boolean die;
62
63 private Socket socket;
64 private InputStream in;
65 private OutputStream out;
66 private long offset;
67
68
69
70 public OpenNapUploadRunner(OpenNapUpload parent, UploadSocket u)
71 {
72 this.parent = parent;
73
74 if (u != null) {
75 this.socket = u.socket;
76 this.in = u.in;
77 this.offset = u.offset;
78 }
79 }
80
81
82
83 public void run()
84 {
85 boolean messageSent = false;
86 try {
87 if (socket == null) {
88 OpenNapUser user = (OpenNapUser)parent.getPeer();
89 connect(user.getHost(), user.getPort());
90 }
91 else {
92 connect();
93 }
94
95 MessageHandler.send(new DownloadingFileMessage());
96 messageSent = true;
97
98 parent.setState(State.UPLOADING);
99
100 upload();
101
102 parent.setState(State.SUCCEEDED);
103 }
104 catch (IOException e) {
105 logger.debug("upload failed", e);
106 parent.setState(State.STOPPED, NetHelper.getErrorMessage(e));
107 }
108 catch (InterruptedException e) {
109 logger.debug("upload aborted");
110 parent.setState(State.STOPPED);
111 }
112 finally {
113 close();
114
115 if (messageSent) {
116 MessageHandler.send(new DownloadCompleteMessage());
117 }
118 }
119 }
120
121 public void stop()
122 {
123 die = true;
124 }
125
126 private void close()
127 {
128 try {
129 if (socket != null)
130 socket.close();
131 if (in != null)
132 in.close();
133 if (out != null)
134 out.close();
135 }
136 catch (IOException e) {
137 }
138 }
139
140 /***
141 * Opens socket and requests file.
142 */
143 private void connect(String ip, int port) throws IOException
144 {
145 logger.debug("opening socket to " + ip + ":" + port);
146
147
148 socket = NetHelper.connect(ip, port, CONNECT_TIMEOUT);
149 socket.setSoTimeout(CONNECT_TIMEOUT);
150
151 out = socket.getOutputStream();
152 in = new BufferedInputStream(socket.getInputStream());
153
154 String message;
155
156
157 char c = (char)in.read();
158 if (c != '1') {
159 throw new IOException(XNap.tr("invalid request"));
160 }
161
162 message = "SEND";
163 out.write(message.getBytes());
164 out.flush();
165
166 message = parent.getServer().getLocalPeer().getName() + " \""
167 + parent.getRequestFilename() + "\" " + parent.getFilesize();
168 logger.debug("> " + message);
169 out.write(message.getBytes());
170 out.flush();
171
172 byte data[] = new byte[1000];
173 int j = in.read(data);
174
175 if (j <= 0) {
176 throw new IOException(XNap.tr("Socket error"));
177 }
178
179 String response = new String(data, 0, j);
180 logger.debug("< " + response);
181 try {
182 offset = Long.parseLong(response);
183 }
184 catch (NumberFormatException e) {
185 throw new IOException(XNap.tr("invalid request"));
186 }
187
188 logger.debug("offset: " + response);
189 }
190
191 private void connect() throws IOException
192 {
193 out = socket.getOutputStream();
194 socket.setSoTimeout(CONNECT_TIMEOUT);
195
196
197 long size = parent.getFile().length();
198 out.write((new Long(size)).toString().getBytes());
199 out.flush();
200 }
201
202 /***
203 *
204 * <p>PRECONDITION<br>
205 * socket != null, in != null, out != null
206 */
207 private void upload() throws IOException, InterruptedException
208 {
209 byte[] buf = new byte[512];
210
211
212 out = new ThrottledOutputStream(out);
213
214 BufferedInputStream inFile = new BufferedInputStream
215 (new FileInputStream(parent.getFile()));
216
217 if (inFile.skip(offset) != offset) {
218 throw new IOException(XNap.tr("invalid offset"));
219 }
220 parent.setTotalBytesTransferred(offset);
221
222 while (!die) {
223 int len = inFile.read(buf, 0, buf.length);
224 if (len <= 0) {
225 break;
226 }
227
228 out.write(buf, 0, len);
229
230 parent.commit(len);
231 }
232
233 if (die) {
234 throw new InterruptedException();
235 }
236 }
237
238 }
239