1 /*****************************************************/
\r
2 /* This java file is a part of the */
\r
4 /* - Plouf's Java IRC Client - */
\r
6 /* Copyright (C) 2002 - 2005 Philippe Detournay */
\r
8 /* All contacts : theplouf@yahoo.com */
\r
10 /* PJIRC is free software; you can redistribute */
\r
11 /* it and/or modify it under the terms of the GNU */
\r
12 /* General Public License as published by the */
\r
13 /* Free Software Foundation; version 2 or later of */
\r
16 /* PJIRC is distributed in the hope that it will */
\r
17 /* be useful, but WITHOUT ANY WARRANTY; without */
\r
18 /* even the implied warranty of MERCHANTABILITY or */
\r
19 /* FITNESS FOR A PARTICULAR PURPOSE. See the GNU */
\r
20 /* General Public License for more details. */
\r
22 /* You should have received a copy of the GNU */
\r
23 /* General Public License along with PJIRC; if */
\r
24 /* not, write to the Free Software Foundation, */
\r
25 /* Inc., 59 Temple Place, Suite 330, Boston, */
\r
26 /* MA 02111-1307 USA */
\r
28 /*****************************************************/
\r
30 package irc.dcc.prv;
\r
32 import irc.IRCConfiguration;
\r
33 import irc.IRCObject;
\r
34 import irc.IRCTextProvider;
\r
35 import irc.ListenerGroup;
\r
37 import irc.ServerListener;
\r
39 import irc.dcc.DCCFile;
\r
41 import java.io.BufferedInputStream;
\r
42 import java.io.BufferedOutputStream;
\r
43 import java.io.File;
\r
44 import java.io.IOException;
\r
45 import java.io.InputStream;
\r
46 import java.io.OutputStream;
\r
47 import java.net.InetAddress;
\r
48 import java.net.ServerSocket;
\r
49 import java.net.Socket;
\r
50 import java.util.Enumeration;
\r
51 import java.util.Vector;
\r
54 * The dcc file handler. There is a handler for each file transfert.
\r
56 public class DCCFileHandler extends IRCObject implements Server, Runnable {
\r
57 private Socket _socket;
\r
58 private ServerSocket _serverSocket;
\r
59 private Thread _thread;
\r
61 private OutputStream _os;
\r
62 private InputStream _is;
\r
63 private DCCFile _file;
\r
65 private int _action;
\r
67 private boolean _listening;
\r
68 private boolean _connected;
\r
69 private ListenerGroup _listeners;
\r
72 * Create a new DCCFileHandler.
\r
75 * the global configuration.
\r
79 * the file to send or receive.
\r
81 public DCCFileHandler(IRCConfiguration config, String remoteNick, File f) {
\r
86 _file = new DCCFile(config, f, this);
\r
87 _listeners = new ListenerGroup();
\r
91 public void release() {
\r
107 public void receive(String ip, String port, String size) {
\r
108 _size = new Integer(size).intValue();
\r
109 _file.prepareReceive(_size);
\r
110 _serverSocket = null;
\r
112 long iip = new Long(ip).longValue();
\r
113 int b1 = (int) (iip & 255);
\r
114 int b2 = (int) ((iip >> 8) & 255);
\r
115 int b3 = (int) ((iip >> 16) & 255);
\r
116 int b4 = (int) ((iip >> 24) & 255);
\r
117 ip = b4 + "." + b3 + "." + b2 + "." + b1;
\r
120 _socket = _ircConfiguration.getSecurityProvider().getSocket(ip, new Integer(port).intValue());
\r
121 _is = new BufferedInputStream(_socket.getInputStream());
\r
122 _os = new BufferedOutputStream(_socket.getOutputStream());
\r
123 _thread = new Thread(this, "DCCFile thread");
\r
125 } catch (Exception e) {
\r
126 _ircConfiguration.internalError("receive failure", e, "plouf@pjirc.com");
\r
132 * Send the file in passive mode.
\r
134 * @return the string to send to the remote peer to initiate the transfert.
\r
136 public String send() {
\r
140 _serverSocket = _ircConfiguration.getSecurityProvider().getServerSocket(0);
\r
141 int port = _serverSocket.getLocalPort();
\r
143 InetAddress addr = _ircConfiguration.getSecurityProvider().getLocalHost();
\r
144 byte[] ip = addr.getAddress();
\r
159 long high = (b1 << 24) + (b2 << 16) + (b3 << 8) + b4;
\r
161 _file.prepareSend();
\r
162 int size = _file.getSize();
\r
163 String sip = "" + high;
\r
164 _listening = false;
\r
165 _thread = new Thread(this, "DCCFile thread");
\r
167 while (!_listening)
\r
169 return sip + " " + port + " " + size;
\r
170 } catch (Exception e) {
\r
175 private void writeConf(OutputStream os, int v) throws IOException {
\r
176 os.write((v >> 24) & 255);
\r
177 os.write((v >> 16) & 255);
\r
178 os.write((v >> 8) & 255);
\r
179 os.write((v) & 255);
\r
183 private int readConf(InputStream is) throws IOException {
\r
184 int b1 = is.read();
\r
187 int b2 = is.read();
\r
190 int b3 = is.read();
\r
193 int b4 = is.read();
\r
196 return (b1 << 24) + (b2 << 16) + (b3 << 8) + b4;
\r
199 private void connected() {
\r
201 _listeners.sendEventAsync("serverConnected", this);
\r
204 private void disconnected() {
\r
205 _connected = false;
\r
206 _listeners.sendEventAsync("serverDisconnected", this);
\r
210 public void run() {
\r
211 byte[] buffer = new byte[4096];
\r
212 if (_action == 1) // receive
\r
217 while (_size - read > 0) {
\r
218 int r = _is.read(buffer, 0, buffer.length);
\r
220 throw new Exception(getText(IRCTextProvider.DCC_STREAM_CLOSED));
\r
222 _file.bytesReceived(buffer, 0, r);
\r
224 writeConf(_os, read);
\r
226 writeConf(_os, _size);
\r
227 _file.fileReceived();
\r
228 } catch (Exception e) {
\r
229 e.printStackTrace();
\r
230 _file.fileReceiveFailed();
\r
234 } else if (_action == 2) // send
\r
238 _serverSocket.setSoTimeout(30000);
\r
239 _socket = _serverSocket.accept();
\r
240 _os = new BufferedOutputStream(_socket.getOutputStream());
\r
241 _is = new BufferedInputStream(_socket.getInputStream());
\r
243 int size = _file.getSize();
\r
246 while (toread > 0) {
\r
247 int r = _file.readBytes(buffer, 0, buffer.length);
\r
249 throw new Exception(getText(IRCTextProvider.DCC_STREAM_CLOSED));
\r
250 _os.write(buffer, 0, r);
\r
253 if (_is.available() > 0)
\r
254 rec = readConf(_is);
\r
257 while (rec != size) {
\r
258 rec = readConf(_is);
\r
262 } catch (Exception e) {
\r
263 e.printStackTrace();
\r
264 _file.fileSentFailed();
\r
272 private void cleanup() {
\r
274 if (_socket != null)
\r
276 if (_serverSocket != null)
\r
277 _serverSocket.close();
\r
280 } catch (Exception e) {
\r
281 _ircConfiguration.internalError("cleanup failure", e, "plouf@pjirc.com");
\r
286 * Close the current transfert.
\r
288 public void close() {
\r
293 public void say(String destination, String str) {
\r
298 public void execute(String str) {
\r
303 public void sendStatusMessage(String str) {
\r
308 public String getNick() {
\r
313 public String getUserName() {
\r
318 public void connect() {
\r
323 public void disconnect() {
\r
328 public boolean isConnected() {
\r
333 public Enumeration getSources() {
\r
334 Vector v = new Vector();
\r
336 v.insertElementAt(_file, v.size());
\r
337 return v.elements();
\r
341 public void enumerateSourcesAsCreated(ServerListener l) {
\r
343 l.sourceCreated(_file, this, new Boolean(true));
\r
347 public void enumerateSourcesAsRemoved(ServerListener l) {
\r
349 l.sourceRemoved(_file, this);
\r
353 public void setDefaultSource(Source source) {
\r
358 public void addServerListener(ServerListener l) {
\r
359 _listeners.addListener(l);
\r
363 public void removeServerListener(ServerListener l) {
\r
364 _listeners.removeListener(l);
\r
368 public void leave() {
\r
370 long time = System.currentTimeMillis();
\r
371 while (isConnected()) {
\r
374 if (System.currentTimeMillis() - time > 10000)
\r
376 } catch (InterruptedException ex) {
\r
380 _listeners.sendEvent("sourceRemoved", _file, this);
\r
381 _listeners.sendEvent("serverLeft", this);
\r
386 public String getServerName() {
\r