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.IOException;
24 import java.io.InputStream;
25 import java.io.InterruptedIOException;
26 import java.io.OutputStream;
27 import java.net.ServerSocket;
28 import java.net.Socket;
29 import java.net.SocketException;
30 import java.util.List;
31 import java.util.Vector;
32
33 import org.apache.log4j.Logger;
34 import org.xnap.plugin.opennap.net.msg.MessageHandler;
35 import org.xnap.plugin.opennap.net.msg.client.ChangeDataPortMessage;
36 import org.xnap.util.PortRange;
37
38
39
40 public class OpenNapListener {
41
42
43
44
45
46 protected static Logger logger = Logger.getLogger(ListenerThread.class);
47
48 private PortRange range = null;
49 private ListenerThread runner = null;
50
51 private List listeners = new Vector();
52
53
54
55 public OpenNapListener(PortRange range)
56 {
57 setPortRange(range);
58 }
59
60 public OpenNapListener()
61 {
62 }
63
64
65
66 public void addSocketListener(SocketListener s)
67 {
68 listeners.add(s);
69 }
70
71 public void removeSocketListener(SocketListener s)
72 {
73 listeners.remove(s);
74 }
75
76 public int getPort()
77 {
78 return (runner != null) ? runner.getPort() : 0;
79 }
80
81 public void die()
82 {
83 if (runner != null) {
84 runner.die();
85 runner = null;
86 }
87 }
88
89 private void start(int port)
90 {
91 if (range != null) {
92 ServerSocket socket = null;
93
94 if (port != 0) {
95 try {
96
97 socket = new ServerSocket(port);
98 }
99 catch (IOException e) {
100 }
101 }
102
103 if (socket == null) {
104
105 for (PortRange.IntIterator i = range.random(); i.hasNext();) {
106 try {
107 socket = new ServerSocket(i.next());
108 break;
109 }
110 catch (IOException e) {
111 }
112 }
113 }
114
115 if (socket != null) {
116 runner = new ListenerThread(socket);
117 runner.start();
118 }
119 else {
120 logger.debug("could not start listener on "
121 + range.toString());
122 }
123 }
124 }
125
126 private void restart(int port)
127 {
128 int oldPort = getPort();
129
130 die();
131 start(port);
132
133 if (oldPort != getPort()) {
134
135 MessageHandler.send(new ChangeDataPortMessage(getPort()));
136 }
137
138 }
139
140 private void restart()
141 {
142 restart(0);
143 }
144
145 /***
146 * Sets a new port range and restarts socket thread if needed.
147 */
148 public void setPortRange(PortRange newValue)
149 {
150 PortRange oldValue = range;
151 range = newValue;
152
153 if (newValue != null && newValue.contains(getPort())) {
154
155 return;
156 }
157
158 restart();
159 }
160
161 private void fireSocketReceived(IncomingSocket s)
162 {
163 Object[] l = listeners.toArray();
164
165 if (l != null) {
166 for (int i = l.length - 1; i >= 0; i--) {
167 if (((SocketListener)l[i]).socketReceived(s)) {
168 return;
169 }
170 }
171 }
172
173 s.close();
174 }
175
176
177
178 private class ListenerThread extends Thread {
179
180 private ServerSocket listenerSocket = null;
181 private boolean die = false;
182
183 public ListenerThread(ServerSocket listenerSocket)
184 {
185 super("OpenNapListener :" + listenerSocket.getLocalPort());
186
187 this.listenerSocket = listenerSocket;
188 }
189
190 public void die()
191 {
192 die = true;
193 }
194
195 public int getPort()
196 {
197 return listenerSocket.getLocalPort();
198 }
199
200 private void handleSocket(Socket s)
201 {
202 InputStream in = null;
203 OutputStream out = null;
204
205 try {
206 in = new BufferedInputStream(s.getInputStream());
207 out = s.getOutputStream();
208
209 out.write('1');
210 out.flush();
211
212 byte data[] = new byte[2048];
213 in.mark(8);
214 int i = in.read(data, 0, 8);
215
216 if (i > 0) {
217 String response = new String(data, 0, i);
218
219 logger.debug("received: " + response);
220 in.reset();
221
222 if (response.startsWith("GETLIST")) {
223 in.skip(7);
224 fireSocketReceived(new BrowseUploadSocket(s, in));
225 logger.debug("creating BrowseUploadSocket");
226 }
227 else if (response.startsWith("GET")) {
228 in.skip(3);
229 fireSocketReceived(new UploadSocket(s, in));
230 logger.debug("creating UploadSocket");
231 }
232 else if (response.startsWith("SENDLIST")) {
233
234 in.skip(8);
235 fireSocketReceived(new BrowseDownloadSocket(s, in));
236 logger.debug("creating BrowseDownloadSocket");
237 }
238 else if (response.startsWith("SEND")) {
239 in.skip(4);
240
241 fireSocketReceived(new DownloadSocket(s, in));
242 logger.debug("creating DownloadSocket");
243 }
244 else {
245 throw new IOException("invalid request: " + response);
246 }
247
248 }
249 else {
250 throw new IOException("empty request");
251 }
252 }
253 catch (IOException e) {
254 logger.warn("invalid listener request", e);
255
256 try {
257 if (s != null) {
258 s.close();
259 }
260 if (in != null) {
261 in.close();
262 }
263 if (out != null) {
264 out.close();
265 }
266 }
267 catch (IOException ioe) {
268 }
269 }
270 }
271
272
273 public void run()
274 {
275 boolean restart = false;
276 logger.debug("started listener on port " + getPort());
277
278 try {
279 listenerSocket.setSoTimeout(10 * 1000);
280 }
281 catch(SocketException e) {
282 restart = true;
283 die = true;
284 }
285
286 while(!die) {
287 Socket socket = null;
288 try {
289 socket = listenerSocket.accept();
290
291
292 socket.setSoTimeout(30 * 1000);
293 }
294 catch(InterruptedIOException e) {
295 continue;
296 }
297 catch(IOException e) {
298 restart = true;
299 break;
300 }
301
302 if (socket != null) {
303 handleSocket(socket);
304 }
305 }
306
307 try {
308 listenerSocket.close();
309 }
310 catch(IOException e) {
311 }
312
313 logger.debug("stopped listener on port " + getPort());
314
315 if (restart) {
316
317 logger.debug("listener died unexpectively, restarting");
318 restart(getPort());
319 }
320 }
321
322 }
323
324 }