]> git.somenet.org - irc/pjirc-ng.git/blob - src/main/java/irc/dcc/prv/DCCChatServer.java
Pjirc 2.2.1 as available on the net, reformatted and made it compile.
[irc/pjirc-ng.git] / src / main / java / irc / dcc / prv / DCCChatServer.java
1 /*****************************************************/\r
2 /*          This java file is a part of the          */\r
3 /*                                                   */\r
4 /*           -  Plouf's Java IRC Client  -           */\r
5 /*                                                   */\r
6 /*   Copyright (C)  2002 - 2005 Philippe Detournay   */\r
7 /*                                                   */\r
8 /*         All contacts : theplouf@yahoo.com         */\r
9 /*                                                   */\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
14 /*  the License.                                     */\r
15 /*                                                   */\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
21 /*                                                   */\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
27 /*                                                   */\r
28 /*****************************************************/\r
29 \r
30 package irc.dcc.prv;\r
31 \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
38 import irc.Server;\r
39 import irc.ServerListener;\r
40 import irc.Source;\r
41 import irc.dcc.DCCChat;\r
42 \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
48 \r
49 /**\r
50  * The DCCChat server. There is a distinct DCCChat server for each active\r
51  * DCCChat.\r
52  */\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
65 \r
66         /**\r
67          * Create a new DCCChat server.\r
68          * \r
69          * @param config\r
70          *          the global irc configuration.\r
71          * @param thisNick\r
72          *          the local nick.\r
73          * @param remoteNick\r
74          *          the remote nick.\r
75          */\r
76         public DCCChatServer(IRCConfiguration config, String thisNick, String remoteNick) {\r
77                 super(config);\r
78                 _action = 0;\r
79                 _listeners = new ListenerGroup();\r
80                 _remoteNick = remoteNick;\r
81                 _thisNick = thisNick;\r
82                 _connected = false;\r
83                 _chat = new DCCChat(_ircConfiguration, this, _remoteNick);\r
84         }\r
85 \r
86         @Override\r
87         public void addServerListener(ServerListener l) {\r
88                 _listeners.addListener(l);\r
89         }\r
90 \r
91         @Override\r
92         public void removeServerListener(ServerListener l) {\r
93                 _listeners.removeListener(l);\r
94         }\r
95 \r
96         @Override\r
97         public void connect() {\r
98                 // nothing here\r
99         }\r
100 \r
101         @Override\r
102         public void disconnect() {\r
103                 close();\r
104         }\r
105 \r
106         @Override\r
107         public boolean isConnected() {\r
108                 return _connected;\r
109         }\r
110 \r
111         @Override\r
112         public Enumeration getSources() {\r
113                 Vector v = new Vector();\r
114                 if (_chat != null)\r
115                         v.insertElementAt(_chat, 0);\r
116                 return v.elements();\r
117         }\r
118 \r
119         @Override\r
120         public void enumerateSourcesAsCreated(ServerListener lis) {\r
121                 if (_chat != null)\r
122                         lis.sourceCreated(_chat, this, new Boolean(_action == 2));\r
123         }\r
124 \r
125         @Override\r
126         public void enumerateSourcesAsRemoved(ServerListener lis) {\r
127                 if (_chat != null)\r
128                         lis.sourceRemoved(_chat, this);\r
129         }\r
130 \r
131         @Override\r
132         public void setDefaultSource(Source s) {\r
133                 // nothing here\r
134         }\r
135 \r
136         @Override\r
137         public void release() {\r
138                 cleanup();\r
139                 _chat = null;\r
140                 super.release();\r
141         }\r
142 \r
143         /**\r
144          * Open an active connection on the given chat.\r
145          * \r
146          * @param ip\r
147          *          the ip to contact.\r
148          * @param port\r
149          *          the port to contact.\r
150          */\r
151         public void openActive(String ip, String port) {\r
152                 _serverSocket = null;\r
153                 _action = 1;\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
160 \r
161                 try {\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
165                         _thread.start();\r
166                 } catch (Exception e) {\r
167                         _ircConfiguration.internalError("openActive failure", e, "plouf@pjirc.com");\r
168                 }\r
169 \r
170         }\r
171 \r
172         /**\r
173          * Open a passive connection on the given chat.\r
174          * \r
175          * @return the string to send to the remote peer to begin the communication.\r
176          */\r
177         public String openPassive() {\r
178                 _action = 2;\r
179                 _socket = null;\r
180                 try {\r
181                         _serverSocket = _ircConfiguration.getSecurityProvider().getServerSocket(0);\r
182                         int port = _serverSocket.getLocalPort();\r
183 \r
184                         InetAddress addr = _ircConfiguration.getSecurityProvider().getLocalHost();\r
185                         byte[] ip = addr.getAddress();\r
186 \r
187                         int b1 = ip[0];\r
188                         if (b1 < 0)\r
189                                 b1 += 256;\r
190                         int b2 = ip[1];\r
191                         if (b2 < 0)\r
192                                 b2 += 256;\r
193                         int b3 = ip[2];\r
194                         if (b3 < 0)\r
195                                 b3 += 256;\r
196                         int b4 = ip[3];\r
197                         if (b4 < 0)\r
198                                 b4 += 256;\r
199 \r
200                         long high = (b1 << 24) + (b2 << 16) + (b3 << 8) + b4;\r
201 \r
202                         String sip = "" + high;\r
203                         _listening = false;\r
204                         _thread = new Thread(this, "DCCChat thread");\r
205                         _thread.start();\r
206                         while (!_listening)\r
207                                 Thread.yield();\r
208                         return sip + " " + port;\r
209                 } catch (Exception e) {\r
210                         e.printStackTrace();\r
211                         return "";\r
212                 }\r
213         }\r
214 \r
215         private void reportChat(String str) {\r
216                 EventDispatcher.dispatchEventAsync(_chat, "report", new Object[] { str });\r
217         }\r
218 \r
219         private void messageChat(String src, String str) {\r
220                 EventDispatcher.dispatchEventAsync(_chat, "messageReceived", new Object[] { src, str });\r
221         }\r
222 \r
223         @Override\r
224         public void run() {\r
225                 boolean terminated = false;\r
226                 if (_action == 2) {\r
227                         try {\r
228                                 _listening = true;\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
235                                 return;\r
236                         }\r
237                 }\r
238                 reportChat(getText(IRCTextProvider.DCC_CONNECTION_ESTABLISHED));\r
239                 _connected = true;\r
240                 _listeners.sendEventAsync("serverConnected", this);\r
241                 while (!terminated) {\r
242                         try {\r
243                                 String line = _handler.read();\r
244                                 if (line == null)\r
245                                         throw new Exception(getText(IRCTextProvider.DCC_CONNECTION_CLOSED));\r
246                                 try {\r
247                                         messageChat(_remoteNick, line);\r
248                                 } catch (Exception e) {\r
249                                         _ircConfiguration.internalError("internal error", e, "plouf@pjirc.com");\r
250                                 }\r
251                         } catch (Exception e) {\r
252                                 terminated = true;\r
253                                 reportChat(getText(IRCTextProvider.DCC_ERROR, e.getMessage()));\r
254                         }\r
255                 }\r
256                 _connected = false;\r
257                 _listeners.sendEventAsync("serverDisconnected", this);\r
258                 cleanup();\r
259         }\r
260 \r
261         @Override\r
262         public void say(String destination, String str) {\r
263                 if (destination.equals(_remoteNick))\r
264                         sendString(str);\r
265                 else\r
266                         _chat.report(getText(IRCTextProvider.DCC_ERROR, getText(IRCTextProvider.DCC_UNABLE_TO_SEND_TO, destination)));\r
267         }\r
268 \r
269         @Override\r
270         public void execute(String str) {\r
271                 _chat.report(getText(IRCTextProvider.DCC_BAD_CONTEXT));\r
272         }\r
273 \r
274         private void sendString(String str) {\r
275                 try {\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
281                 }\r
282         }\r
283 \r
284         @Override\r
285         public void sendStatusMessage(String str) {\r
286                 if (_chat != null)\r
287                         _chat.report(str);\r
288         }\r
289 \r
290         private void cleanup() {\r
291                 try {\r
292                         if (_socket != null)\r
293                                 _socket.close();\r
294                         if (_serverSocket != null)\r
295                                 _serverSocket.close();\r
296                         _handler.close();\r
297                 } catch (Exception e) {\r
298                         _ircConfiguration.internalError("cleanup failure", e, "plouf@pjirc.com");\r
299                 }\r
300         }\r
301 \r
302         /**\r
303          * Close this communication.\r
304          */\r
305         public void close() {\r
306                 cleanup();\r
307         }\r
308 \r
309         @Override\r
310         public void leave() {\r
311                 disconnect();\r
312                 long time = System.currentTimeMillis();\r
313                 while (isConnected()) {\r
314                         try {\r
315                                 Thread.sleep(100);\r
316                                 if (System.currentTimeMillis() - time > 10000)\r
317                                         break;\r
318                         } catch (InterruptedException ex) {\r
319                                 // ignore it...\r
320                         }\r
321                 }\r
322                 _listeners.sendEvent("sourceRemoved", _chat, this);\r
323                 _listeners.sendEvent("serverLeft", this);\r
324                 _chat.release();\r
325         }\r
326 \r
327         @Override\r
328         public String getNick() {\r
329                 return _thisNick;\r
330         }\r
331 \r
332         @Override\r
333         public String getUserName() {\r
334                 return "";\r
335         }\r
336 \r
337         @Override\r
338         public String getServerName() {\r
339                 return getNick();\r
340         }\r
341 }\r