ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/i-scream/projects/cms/source/server/uk/org/iscream/cms/server/clientinterface/TCPControlHandler.java
Revision: 1.15
Committed: Wed Feb 21 19:11:28 2001 UTC (23 years, 3 months ago) by tdb
Branch: MAIN
Changes since 1.14: +12 -4 lines
Log Message:
Modification to the Queue system;
- interval of monitor is now configurable.
- attempt to identify each Queue better, although this is still hard.

File Contents

# Content
1 //---PACKAGE DECLARATION---
2 package uk.ac.ukc.iscream.clientinterface;
3
4 //---IMPORTS---
5 import uk.ac.ukc.iscream.util.*;
6 import uk.ac.ukc.iscream.componentmanager.*;
7 import uk.ac.ukc.iscream.core.*;
8 import java.net.Socket;
9 import java.net.ServerSocket;
10 import java.io.InputStream;
11 import java.io.OutputStream;
12 import java.io.IOException;
13 import java.io.BufferedReader;
14 import java.io.PrintWriter;
15 import java.io.InputStreamReader;
16
17
18 /**
19 * Acts as a Control Handler to a TCP based client.
20 *
21 * @author $Author: tdb1 $
22 * @version $Id: TCPControlHandler.java,v 1.14 2001/02/12 02:23:53 tdb1 Exp $
23 */
24 class TCPControlHandler extends Thread {
25
26 //---FINAL ATTRIBUTES---
27
28 /**
29 * The current CVS revision of this class
30 */
31 public final String REVISION = "$Revision: 1.14 $";
32
33 /**
34 * This is our protocol version. It is hardcoded to ensure
35 * that it doesn't get accidently changed. A change to the
36 * protocol would also require changing this classes code !
37 */
38 public static final String PROTOVER = "PROTOCOL 1.1";
39
40 //---STATIC METHODS---
41
42 //---CONSTRUCTORS---
43
44 /**
45 * Construct a new TCPControlHandler, and setup the reader
46 * and writer for the new Socket.
47 *
48 * @param socket The Socket connected to the new Client
49 * @param packetSorter A reference to the PacketSorter in the component
50 * @param queueMonitorInterval The interval at which to monitor our Queue
51 */
52 public TCPControlHandler(Socket socket, PacketSorter packetSorter, int queueMonitorInterval) throws IOException {
53 _socket = socket;
54 _packetSorter = packetSorter;
55 _queueMonitorInterval = queueMonitorInterval;
56 // setup the reader & writer
57 _socketIn = new BufferedReader(new InputStreamReader(_socket.getInputStream()));
58 _socketOut = new PrintWriter(_socket.getOutputStream(), true);
59 // set the default hostlist to "all host", for backward compatibility
60 _hostList = "";
61 _logger.write(toString(), Logger.SYSINIT, "created");
62 }
63
64 //---PUBLIC METHODS---
65
66 /**
67 * This method initiates the thread, setting things up, and then
68 * reading commands from the Client. It handles setting up of the
69 * DataHandler, and clean shutting down.
70 */
71 public void run() {
72 boolean run = true;
73 // Tell the client our protocol, and ask it for it's name
74 try {
75 send(PROTOVER);
76 _clientName = _socketIn.readLine();
77 if(_clientName==null) {
78 throw new IOException("Fatal error reading from client");
79 }
80 sendOK();
81 }
82 catch(IOException e) {
83 _logger.write(toString(), Logger.FATAL, "Fatal error, shutdown pending");
84 run=false;
85 }
86
87 _logger.write(toString(), Logger.DEBUG, "Client has connected: "+_clientName);
88
89 // loop until we decide to shutdown (run=false)
90 while(run) {
91 try {
92 String cmd = _socketIn.readLine();
93 if(cmd==null) {
94 throw new IOException("Fatal error reading from client");
95 }
96 // make a decision about what to do
97 if(cmd.equals("STARTCONFIG")) {
98 // get the configuration for this client
99 Configuration myConfig = _configManager.getConfiguration("Client."+_clientName);
100 sendOK();
101 // get properties
102 cmd = _socketIn.readLine();
103 if(cmd==null) {
104 throw new IOException("Fatal error reading from client");
105 }
106 // provide all the requested properties
107 while(!cmd.equals("ENDCONFIG")) {
108 // client is restricted to this properties
109 if(cmd.startsWith("Client.") || cmd.startsWith("Host.")) {
110 try {
111 String returnedProperty = myConfig.getProperty(cmd);
112 send(returnedProperty);
113 }
114 catch (org.omg.CORBA.MARSHAL e) {
115 sendERROR();
116 }
117 }
118 else {
119 sendERROR();
120 }
121 cmd = _socketIn.readLine();
122 if(cmd==null) {
123 throw new IOException("Fatal error reading from client");
124 }
125 }
126 sendOK();
127 _logger.write(toString(), Logger.DEBUG, "Client has been configured");
128
129 }
130 else if(cmd.equals("STARTDATA")) {
131 // if we don't have a DataHandler, set one up
132 if(_dataHandler == null) {
133 // create a serversocket
134 ServerSocket ss = new ServerSocket(0);
135 // get the port
136 String port = new Integer(ss.getLocalPort()).toString();
137 // tell the client the port
138 send(port);
139 // wait for the client to connect
140 Socket s = ss.accept();
141 // when we get the Socket back, give it to the data thread
142 TCPDataHandler dh = new TCPDataHandler(s);
143 // register the DataHandler's queue, giving the host list
144 _packetSorter.register(dh.getQueue(), _hostList);
145 // startup a monitor on the DataHandler's queue, every minute
146 String queueName = _name + " TCPHandler:"+_socket.getInetAddress().getHostName();
147 dh.getQueue().startMonitor(_queueMonitorInterval*1000, _packetSorter.getQueue(), queueName);
148 // start up the DataHandler
149 dh.start();
150 // Hold a reference to the DataHandler, so we can stop it later
151 _dataHandler = dh;
152 sendOK();
153 _logger.write(toString(), Logger.DEBUG, "Data stream started at Clients Request on port: "+port);
154 }
155 else {
156 sendERROR();
157 }
158 }
159 else if(cmd.equals("STOPDATA")) {
160 // attempt to close the data channel
161 if(closeData()) {
162 sendOK();
163 _logger.write(toString(), Logger.DEBUG, "Data stream stopped at Clients Request");
164 }
165 else {
166 sendERROR();
167 }
168 }
169 else if(cmd.equals("SETHOSTLIST")) {
170 // we can only set the host list when
171 // the DataHandler is not connected
172 if(_dataHandler == null) {
173 sendOK();
174 // read and set the host list
175 cmd = _socketIn.readLine();
176 if(cmd==null) {
177 throw new IOException("Fatal error reading from client");
178 }
179 _hostList = cmd;
180 sendOK();
181 }
182 else {
183 sendERROR();
184 }
185 }
186 else if(cmd.equals("DISCONNECT")) {
187 // we going to disconnect, so lets stop the main loop
188 run=false;
189 // if there is a DataHandler, we'd best shut it down
190 if(closeData()) {
191 _logger.write(toString(), Logger.DEBUG, "Data stream stopped at Clients Request");
192 }
193 // say bye to the client
194 sendOK();
195 // close the reader, writer and Socket
196 _socketIn.close();
197 _socketOut.close();
198 _socket.close();
199 _logger.write(toString(), Logger.DEBUG, "Closing at Clients Request");
200 }
201 else {
202 sendERROR();
203 }
204 }
205 catch(IOException e) {
206 // if we get an exception, the client has probably left, so we stop
207 run=false;
208 _logger.write(toString(), Logger.FATAL, "Fatal communication error, shutdown pending");
209 }
210 }
211 _logger.write(toString(), Logger.DEBUG, "Shutting down Control Handler, client has gone.");
212 }
213
214 /**
215 * Overrides the {@link java.lang.Object#toString() Object.toString()}
216 * method to provide clean logging (every class should have this).
217 *
218 * This uses the uk.ac.ukc.iscream.util.NameFormat class
219 * to format the toString()
220 *
221 * @return the name of this class and its CVS revision
222 */
223 public String toString() {
224 return FormatName.getName(
225 _name,
226 getClass().getName(),
227 REVISION);
228 }
229
230 //---PRIVATE METHODS---
231
232 /**
233 * Attempt to close down the DataHandler. This will return
234 * true if it managed to close it down, or false if there
235 * wasn't a DataHandler to close.
236 *
237 * @return whether the channel could be closed
238 */
239 private boolean closeData() {
240 // if we have a DataHandler, shut it down
241 if(_dataHandler != null) {
242 // Deregister the DataHandler, giving the host list
243 _packetSorter.deregister(_dataHandler.getQueue(), _hostList);
244 // Shut down the data handler
245 _dataHandler.shutdown();
246 // Destroy our reference, leaving it for the GC
247 _dataHandler = null;
248 return true;
249 }
250 else {
251 return false;
252 }
253 }
254
255 /**
256 * Send an OK message to the outgoing Socket
257 */
258 private void sendOK() {
259 send("OK");
260 }
261
262 /**
263 * Send an ERROR message to the outgoing Socket.
264 */
265 private void sendERROR() {
266 send("ERROR");
267 }
268
269 /**
270 * Send any String message to the outgoing Socket.
271 *
272 * @param message The message/command to send.
273 */
274 private void send(String message) {
275 _socketOut.println(message);
276 }
277
278 //---ACCESSOR/MUTATOR METHODS---
279
280 //---ATTRIBUTES---
281
282 /**
283 * This is the friendly identifier of the
284 * component this class is running in.
285 * eg, a Filter may be called "filter1",
286 * If this class does not have an owning
287 * component, a name from the configuration
288 * can be placed here. This name could also
289 * be changed to null for utility classes.
290 */
291 private String _name = ClientInterfaceMain.NAME;
292
293 /**
294 * This holds a reference to the
295 * system logger that is being used.
296 */
297 private Logger _logger = ReferenceManager.getInstance().getLogger();
298
299 /**
300 * A reference to the Configuration Manager the system is using
301 */
302 private ConfigurationManager _configManager = ReferenceManager.getInstance().getCM();
303
304 /**
305 * The socket we are talking on
306 */
307 private Socket _socket;
308
309 /**
310 * A hook to the inbound data from the socket
311 */
312 private BufferedReader _socketIn;
313
314 /**
315 * A hook to the outbound stream for the socket
316 */
317 private PrintWriter _socketOut;
318
319 /**
320 * A reference to the PacketSorter.
321 */
322 private PacketSorter _packetSorter;
323
324 /**
325 * A reference to the DataHandler, if there is one
326 */
327 private TCPDataHandler _dataHandler;
328
329 /**
330 * The name of the Client we're connected to
331 */
332 private String _clientName;
333
334 /**
335 * The host list the Client has requested
336 */
337 private String _hostList;
338
339 /**
340 * The interval at which to monitor our Queue
341 */
342 private int _queueMonitorInterval;
343
344 //---STATIC ATTRIBUTES---
345
346 }