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.CodingHandler;
\r
33 import irc.EventDispatcher;
\r
34 import irc.IRCConfiguration;
\r
35 import irc.IRCObject;
\r
36 import irc.IRCTextProvider;
\r
37 import irc.ListenerGroup;
\r
39 import irc.ServerListener;
\r
41 import irc.dcc.DCCChat;
\r
43 import java.net.InetAddress;
\r
44 import java.net.ServerSocket;
\r
45 import java.net.Socket;
\r
46 import java.util.Enumeration;
\r
47 import java.util.Vector;
\r
50 * The DCCChat server. There is a distinct DCCChat server for each active
\r
53 public class DCCChatServer extends IRCObject implements Runnable, Server {
\r
54 private Socket _socket;
\r
55 private ServerSocket _serverSocket;
\r
56 private CodingHandler _handler;
\r
57 private Thread _thread;
\r
58 private DCCChat _chat;
\r
59 private String _remoteNick;
\r
60 private String _thisNick;
\r
61 private ListenerGroup _listeners;
\r
62 private boolean _listening;
\r
63 private int _action;
\r
64 private boolean _connected;
\r
67 * Create a new DCCChat server.
\r
70 * the global irc configuration.
\r
76 public DCCChatServer(IRCConfiguration config, String thisNick, String remoteNick) {
\r
79 _listeners = new ListenerGroup();
\r
80 _remoteNick = remoteNick;
\r
81 _thisNick = thisNick;
\r
83 _chat = new DCCChat(_ircConfiguration, this, _remoteNick);
\r
87 public void addServerListener(ServerListener l) {
\r
88 _listeners.addListener(l);
\r
92 public void removeServerListener(ServerListener l) {
\r
93 _listeners.removeListener(l);
\r
97 public void connect() {
\r
102 public void disconnect() {
\r
107 public boolean isConnected() {
\r
112 public Enumeration getSources() {
\r
113 Vector v = new Vector();
\r
115 v.insertElementAt(_chat, 0);
\r
116 return v.elements();
\r
120 public void enumerateSourcesAsCreated(ServerListener lis) {
\r
122 lis.sourceCreated(_chat, this, new Boolean(_action == 2));
\r
126 public void enumerateSourcesAsRemoved(ServerListener lis) {
\r
128 lis.sourceRemoved(_chat, this);
\r
132 public void setDefaultSource(Source s) {
\r
137 public void release() {
\r
144 * Open an active connection on the given chat.
\r
147 * the ip to contact.
\r
149 * the port to contact.
\r
151 public void openActive(String ip, String port) {
\r
152 _serverSocket = null;
\r
154 long iip = new Long(ip).longValue();
\r
155 int b1 = (int) (iip & 255);
\r
156 int b2 = (int) ((iip >> 8) & 255);
\r
157 int b3 = (int) ((iip >> 16) & 255);
\r
158 int b4 = (int) ((iip >> 24) & 255);
\r
159 ip = b4 + "." + b3 + "." + b2 + "." + b1;
\r
162 _socket = _ircConfiguration.getSecurityProvider().getSocket(ip, new Integer(port).intValue());
\r
163 _handler = new CodingHandler(_ircConfiguration, _socket.getInputStream(), _socket.getOutputStream());
\r
164 _thread = new Thread(this, "DCCChat thread");
\r
166 } catch (Exception e) {
\r
167 _ircConfiguration.internalError("openActive failure", e, "plouf@pjirc.com");
\r
173 * Open a passive connection on the given chat.
\r
175 * @return the string to send to the remote peer to begin the communication.
\r
177 public String openPassive() {
\r
181 _serverSocket = _ircConfiguration.getSecurityProvider().getServerSocket(0);
\r
182 int port = _serverSocket.getLocalPort();
\r
184 InetAddress addr = _ircConfiguration.getSecurityProvider().getLocalHost();
\r
185 byte[] ip = addr.getAddress();
\r
200 long high = (b1 << 24) + (b2 << 16) + (b3 << 8) + b4;
\r
202 String sip = "" + high;
\r
203 _listening = false;
\r
204 _thread = new Thread(this, "DCCChat thread");
\r
206 while (!_listening)
\r
208 return sip + " " + port;
\r
209 } catch (Exception e) {
\r
210 e.printStackTrace();
\r
215 private void reportChat(String str) {
\r
216 EventDispatcher.dispatchEventAsync(_chat, "report", new Object[] { str });
\r
219 private void messageChat(String src, String str) {
\r
220 EventDispatcher.dispatchEventAsync(_chat, "messageReceived", new Object[] { src, str });
\r
224 public void run() {
\r
225 boolean terminated = false;
\r
226 if (_action == 2) {
\r
229 reportChat(getText(IRCTextProvider.DCC_WAITING_INCOMING));
\r
230 _serverSocket.setSoTimeout(30000);
\r
231 _socket = _serverSocket.accept();
\r
232 _handler = new CodingHandler(_ircConfiguration, _socket.getInputStream(), _socket.getOutputStream());
\r
233 } catch (Exception e) {
\r
234 reportChat(getText(IRCTextProvider.DCC_UNABLE_TO_OPEN_CONNECTION, e.getMessage()));
\r
238 reportChat(getText(IRCTextProvider.DCC_CONNECTION_ESTABLISHED));
\r
240 _listeners.sendEventAsync("serverConnected", this);
\r
241 while (!terminated) {
\r
243 String line = _handler.read();
\r
245 throw new Exception(getText(IRCTextProvider.DCC_CONNECTION_CLOSED));
\r
247 messageChat(_remoteNick, line);
\r
248 } catch (Exception e) {
\r
249 _ircConfiguration.internalError("internal error", e, "plouf@pjirc.com");
\r
251 } catch (Exception e) {
\r
253 reportChat(getText(IRCTextProvider.DCC_ERROR, e.getMessage()));
\r
256 _connected = false;
\r
257 _listeners.sendEventAsync("serverDisconnected", this);
\r
262 public void say(String destination, String str) {
\r
263 if (destination.equals(_remoteNick))
\r
266 _chat.report(getText(IRCTextProvider.DCC_ERROR, getText(IRCTextProvider.DCC_UNABLE_TO_SEND_TO, destination)));
\r
270 public void execute(String str) {
\r
271 _chat.report(getText(IRCTextProvider.DCC_BAD_CONTEXT));
\r
274 private void sendString(String str) {
\r
276 if ((_handler == null) || (!_connected))
\r
277 throw new Exception(getText(IRCTextProvider.DCC_NOT_CONNECTED));
\r
278 _handler.write(str);
\r
279 } catch (Exception e) {
\r
280 _chat.report(getText(IRCTextProvider.DCC_ERROR, e.getMessage()));
\r
285 public void sendStatusMessage(String str) {
\r
290 private void cleanup() {
\r
292 if (_socket != null)
\r
294 if (_serverSocket != null)
\r
295 _serverSocket.close();
\r
297 } catch (Exception e) {
\r
298 _ircConfiguration.internalError("cleanup failure", e, "plouf@pjirc.com");
\r
303 * Close this communication.
\r
305 public void close() {
\r
310 public void leave() {
\r
312 long time = System.currentTimeMillis();
\r
313 while (isConnected()) {
\r
316 if (System.currentTimeMillis() - time > 10000)
\r
318 } catch (InterruptedException ex) {
\r
322 _listeners.sendEvent("sourceRemoved", _chat, this);
\r
323 _listeners.sendEvent("serverLeft", this);
\r
328 public String getNick() {
\r
333 public String getUserName() {
\r
338 public String getServerName() {
\r