1 |
//---PACKAGE DECLARATION--- |
2 |
package uk.ac.ukc.iscream.conient; |
3 |
|
4 |
//---IMPORTS--- |
5 |
import uk.ac.ukc.iscream.util.*; |
6 |
import java.io.*; |
7 |
import java.net.*; |
8 |
import javax.swing.JOptionPane; |
9 |
|
10 |
/** |
11 |
* This is the main thread for the client. |
12 |
* Once started i continually checks it actionQueue |
13 |
* for actions that other areas of the system have placed |
14 |
* there, it then performs those actions. |
15 |
* |
16 |
* Currently this is the main thread where all non-GUI events |
17 |
* are dispatched to. |
18 |
* |
19 |
* @author $Author: tdb1 $ |
20 |
* @version $Id: ConnectionHandler.java,v 1.9 2001/01/24 01:12:30 tdb1 Exp $ |
21 |
*/ |
22 |
public class ConnectionHandler extends Thread { |
23 |
|
24 |
//---FINAL ATTRIBUTES--- |
25 |
|
26 |
/** |
27 |
* The current CVS revision of this class |
28 |
*/ |
29 |
public final String REVISION = "$Revision: 1.9 $"; |
30 |
|
31 |
|
32 |
/** |
33 |
* The hardcoded protocol version that we are using. |
34 |
* Used when handshaking with the server |
35 |
*/ |
36 |
public final double PROTOCOL_VERSION = 1.0; |
37 |
|
38 |
/** |
39 |
* Thread action DONOTHING. |
40 |
* This is an invalid action, but here for completeness |
41 |
* if anything sends this action it will warn appropriately |
42 |
* but do what it says, ie, nothing ;) |
43 |
*/ |
44 |
public static final int DONOTHING = 0; |
45 |
|
46 |
/** |
47 |
* Thread action CONNECT. |
48 |
* Opens the control link to the i-scream server. |
49 |
*/ |
50 |
public static final int CONNECT = 1; |
51 |
|
52 |
/** |
53 |
* Thread action STARTDATA. |
54 |
* Opens the data link to the i-scream server |
55 |
* and prepares all gui data components for data |
56 |
* it then starts all relavant threads going. |
57 |
*/ |
58 |
public static final int STARTDATA = 2; |
59 |
|
60 |
/** |
61 |
* Thread action STOPDATA. |
62 |
* Closes the data link and shuts down all components |
63 |
* that update gui for various things. |
64 |
*/ |
65 |
public static final int STOPDATA = 3; |
66 |
|
67 |
/** |
68 |
* Thread action DISCONNECT. |
69 |
* Checks to see if STOPDATA has been called if not, |
70 |
* it will add STOPDATA and then DISCONNECT to |
71 |
* the action queue and return. If STOPDATA has been |
72 |
* called it closes down the Control Link and tidies up |
73 |
* all relevant threads |
74 |
*/ |
75 |
public static final int DISCONNECT = 4; |
76 |
|
77 |
/** |
78 |
* Thread action QUIT. |
79 |
* Checks the status of the two links, if either |
80 |
* are still up, it queues the appropriate commands |
81 |
* to close them down. It then System.exit(0)'s! |
82 |
*/ |
83 |
public static final int QUIT = 5; |
84 |
|
85 |
//---STATIC METHODS--- |
86 |
|
87 |
//---CONSTRUCTORS--- |
88 |
|
89 |
/** |
90 |
* Constructs new data handler. |
91 |
* Needs a reference to the data panel so that |
92 |
* it can set it processing inBound data |
93 |
* Also gets a reference to the queue that will be |
94 |
* used by other areas of the system to send it actions |
95 |
* |
96 |
* @param data the DataPanel in use |
97 |
* @param actionQueue the actionQueue for this class |
98 |
*/ |
99 |
public ConnectionHandler(DataPanel data, Queue actionQueue) { |
100 |
_data = data; |
101 |
_actionQueue = actionQueue; |
102 |
_myQueue = _actionQueue.getQueue(); |
103 |
} |
104 |
|
105 |
//---PUBLIC METHODS--- |
106 |
|
107 |
|
108 |
/** |
109 |
* Starts this ConnectionHandler running. |
110 |
* This basically runs until told to stop, it gets "actions" |
111 |
* from its actionQueue and switch's on them do determine |
112 |
* what it should do it then carries out the action |
113 |
* |
114 |
* For details on what each action does see the action |
115 |
* types. |
116 |
*/ |
117 |
public void run() { |
118 |
while(_running) { |
119 |
// we wait for a call... |
120 |
int action = 0; |
121 |
try { |
122 |
action = ((Integer) _actionQueue.get(_myQueue)).intValue(); |
123 |
} catch (InvalidQueueException e) { |
124 |
// we 're never going to get this... |
125 |
} |
126 |
|
127 |
// examine our action... |
128 |
// if it was to connect...then we connect... |
129 |
switch(action) { |
130 |
case CONNECT: |
131 |
|
132 |
Object serverQuestion = null; |
133 |
serverQuestion = JOptionPane.showInputDialog(null, "Please enter the name of a server running the I-Scream client interface:", "I-Scream Server", JOptionPane.INFORMATION_MESSAGE); |
134 |
if (serverQuestion instanceof String) { |
135 |
_server = (String) serverQuestion; |
136 |
SwingClient.setControlStatus("Connecting to - " + _server); |
137 |
try { |
138 |
_controlLink = new Socket(_server, _port); |
139 |
_inBound = new BufferedReader(new InputStreamReader(_controlLink.getInputStream())); |
140 |
_outBound = new PrintWriter(_controlLink.getOutputStream()); |
141 |
SwingClient.setControlStatus("Connection Established - " + _server); |
142 |
String response; |
143 |
response = _inBound.readLine(); |
144 |
if (!(Double.parseDouble(response.substring(10, response.length())) > PROTOCOL_VERSION)) { |
145 |
SwingClient.addMessage("WARNING: server is using a newer protocol (" + response + "), please update your client, continuing with old protocol (PROTOCOL " + PROTOCOL_VERSION + ")" ); |
146 |
} else if (!(Double.parseDouble(response.substring(10, response.length())) < PROTOCOL_VERSION)) { |
147 |
throw new IOException("invalid protocol version"); |
148 |
} |
149 |
SwingClient.addMessage("Handshake Success"); |
150 |
|
151 |
// send the name - get from somewhere eventually |
152 |
_outBound.println(_clientName); |
153 |
_outBound.flush(); |
154 |
response = _inBound.readLine(); |
155 |
if (!response.equals("OK")) { |
156 |
throw new IOException("client name rejected - " + response); |
157 |
} |
158 |
SwingClient.addMessage("Control Link Established"); |
159 |
|
160 |
} catch (IOException e) { |
161 |
SwingClient.addMessage("Control Link Error: " + e); |
162 |
SwingClient.setControlStatus("Disconnected"); |
163 |
} |
164 |
} |
165 |
break; |
166 |
case STARTDATA: |
167 |
SwingClient.addMessage("Attempting to open Data Channel"); |
168 |
try { |
169 |
if(_controlLink == null) { |
170 |
_actionQueue.add(new Integer(CONNECT)); |
171 |
_actionQueue.add(new Integer(STARTDATA)); |
172 |
throw new IOException("Control Link not establised - queueing start events"); |
173 |
} |
174 |
String response; |
175 |
_outBound.println("STARTDATA"); |
176 |
_outBound.flush(); |
177 |
response = _inBound.readLine(); |
178 |
|
179 |
// TEMPORARY FIREWALL FIX |
180 |
// allows user to map an ssh pipe... |
181 |
JOptionPane.showMessageDialog(null, "WARNING: about to connect to a port you may not have available!\nPlease ensure you have port \"" + response + "\" of your I-Scream server mapped to " + _server, "FIREWALL WARNING!", JOptionPane.INFORMATION_MESSAGE); |
182 |
SwingClient.setDataStatus("Connecting to - " + _server + ":" + response); |
183 |
try { |
184 |
_dataLink = new Socket(_server, Integer.parseInt(response)); |
185 |
} catch (NumberFormatException e) { |
186 |
throw new IOException("error, invalid data port suggested by server - " + response); |
187 |
} |
188 |
|
189 |
response = _inBound.readLine(); |
190 |
if (!response.equals("OK")) { |
191 |
throw new IOException("server reported error establishing data channel - " + response); |
192 |
} |
193 |
_dataInBound = new BufferedReader(new InputStreamReader(_dataLink.getInputStream())); |
194 |
_dataOutBound = new PrintWriter(_dataLink.getOutputStream()); |
195 |
SwingClient.setDataStatus("Connection Established - " + _server); |
196 |
SwingClient.addMessage("Data Link connection established"); |
197 |
SwingClient.addMessage("Starting data reader"); |
198 |
|
199 |
// here we will do some connect stuff. |
200 |
Queue theQueue = new Queue(); |
201 |
_dataReader = new DataReader(_dataInBound, theQueue); |
202 |
_data.setQueue(theQueue); |
203 |
_data.cleanUpTabs(); |
204 |
new Thread(_data).start(); |
205 |
_dataReader.start(); |
206 |
// finished for us.... |
207 |
} catch (IOException e) { |
208 |
SwingClient.addMessage("Data Link Error: " + e); |
209 |
SwingClient.setDataStatus("Disconnected"); |
210 |
} |
211 |
break; |
212 |
case STOPDATA: |
213 |
SwingClient.addMessage("Attempting to close Data Channel"); |
214 |
try { |
215 |
String response; |
216 |
_outBound.println("STOPDATA"); |
217 |
_outBound.flush(); |
218 |
response = _inBound.readLine(); |
219 |
if (!response.equals("OK")) { |
220 |
throw new IOException("server didn't OK request to stop data channel"); |
221 |
} |
222 |
// kill the data reader - we should wait |
223 |
// for it to die nicely...but we won't yet...we'll kill the socket! ;-p |
224 |
SwingClient.setDataStatus("Disconnecting - " + _server); |
225 |
_dataReader.shutdown(); |
226 |
_dataInBound.close(); |
227 |
_dataOutBound.close(); |
228 |
_dataLink.close(); |
229 |
// get rid of the socket |
230 |
_dataLink = null; |
231 |
SwingClient.setDataStatus("Disconnected"); |
232 |
SwingClient.addMessage("Data Channel closed"); |
233 |
} catch (IOException e) { |
234 |
SwingClient.addMessage("Data Link Error: " + e); |
235 |
SwingClient.setDataStatus("Unknown"); |
236 |
} |
237 |
break; |
238 |
case DISCONNECT: |
239 |
SwingClient.addMessage("Attempting to close Control Channel"); |
240 |
try { |
241 |
if (_dataLink != null) { |
242 |
// we want to tell ourselves to stop it |
243 |
_actionQueue.add(new Integer(STOPDATA)); |
244 |
_actionQueue.add(new Integer(DISCONNECT)); |
245 |
throw new IOException("Warning - Data Channel not closed - attempting to close it!"); |
246 |
} |
247 |
String response; |
248 |
_outBound.println("DISCONNECT"); |
249 |
_outBound.flush(); |
250 |
response = _inBound.readLine(); |
251 |
if (!response.equals("OK")) { |
252 |
throw new IOException("server didn't OK request to stop control channel"); |
253 |
} |
254 |
// then lets go! |
255 |
SwingClient.setControlStatus("Disconnecting - " + _server); |
256 |
_inBound.close(); |
257 |
_outBound.close(); |
258 |
_controlLink.close(); |
259 |
// for good measure |
260 |
_controlLink = null; |
261 |
SwingClient.setControlStatus("Disconnected"); |
262 |
} catch (IOException e) { |
263 |
SwingClient.addMessage("Control Link Error: " + e); |
264 |
SwingClient.setControlStatus("Unknown"); |
265 |
} |
266 |
break; |
267 |
case QUIT: |
268 |
SwingClient.addMessage("Exiting..."); |
269 |
try { |
270 |
// stop data and control if data up |
271 |
if (_dataLink != null) { |
272 |
_actionQueue.add(new Integer(STOPDATA)); |
273 |
_actionQueue.add(new Integer(DISCONNECT)); |
274 |
_actionQueue.add(new Integer(QUIT)); |
275 |
throw new IOException(); |
276 |
} |
277 |
// stop control |
278 |
if (_controlLink != null) { |
279 |
_actionQueue.add(new Integer(DISCONNECT)); |
280 |
_actionQueue.add(new Integer(QUIT)); |
281 |
throw new IOException(); |
282 |
} |
283 |
SwingClient.addMessage("Finished."); |
284 |
// go! |
285 |
System.exit(0); |
286 |
} catch (IOException e) { |
287 |
SwingClient.addMessage("Closing connections..."); |
288 |
} |
289 |
break; |
290 |
} |
291 |
} |
292 |
} |
293 |
|
294 |
//---PRIVATE METHODS--- |
295 |
|
296 |
//---ACCESSOR/MUTATOR METHODS--- |
297 |
|
298 |
//---ATTRIBUTES--- |
299 |
|
300 |
boolean _running = true; |
301 |
SwingClient SwingClient; |
302 |
DataPanel _data; |
303 |
Queue _actionQueue; |
304 |
int _myQueue; |
305 |
String _server; |
306 |
int _port = SwingClient.PORT; |
307 |
Socket _controlLink; |
308 |
Socket _dataLink; |
309 |
BufferedReader _inBound; |
310 |
PrintWriter _outBound; |
311 |
BufferedReader _dataInBound; |
312 |
PrintWriter _dataOutBound; |
313 |
DataReader _dataReader; |
314 |
String _clientName = "Conient"; |
315 |
|
316 |
//---STATIC ATTRIBUTES--- |
317 |
|
318 |
} |