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.10
Committed: Mon Jan 29 02:00:03 2001 UTC (23 years, 4 months ago) by tdb
Branch: MAIN
Changes since 1.9: +17 -2 lines
Log Message:
A bit of checking of the input. It's likely that if we get a null back something
has gone haywire in the communication. This could probably be done better.

File Contents

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