001: /*
002: *
003: *
004: * Copyright 1990-2007 Sun Microsystems, Inc. All Rights Reserved.
005: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER
006: *
007: * This program is free software; you can redistribute it and/or
008: * modify it under the terms of the GNU General Public License version
009: * 2 only, as published by the Free Software Foundation.
010: *
011: * This program is distributed in the hope that it will be useful, but
012: * WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014: * General Public License version 2 for more details (a copy is
015: * included at /legal/license.txt).
016: *
017: * You should have received a copy of the GNU General Public License
018: * version 2 along with this work; if not, write to the Free Software
019: * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
020: * 02110-1301 USA
021: *
022: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
023: * Clara, CA 95054 or visit www.sun.com if you need additional
024: * information or have any questions.
025: */
026: package com.sun.midp.jsr82emul;
027:
028: import java.io.IOException;
029: import java.io.InputStream;
030: import java.io.OutputStream;
031: import javax.microedition.io.SocketConnection;
032: import com.sun.midp.io.BluetoothUrl;
033: import java.util.Hashtable;
034: import java.util.Enumeration;
035:
036: /**
037: * Handles communication with a client.
038: */
039: class ClientHandler implements Runnable {
040: /** Handle that identifies corresponding data on server. */
041: int handle;
042: /** Common handlers counter. */
043: private static int nextHandle = 0;
044:
045: /** Bluetooth address of device or device emulation client belongs to. */
046: byte[] bluetoothAddress = null;
047:
048: /** If not <code>null</code>, IP address of computer client works at. */
049: byte[] ipAddress = null;
050:
051: /**
052: * Keeps device state if this handler handles device,
053: * <code>null</code> otherwise.
054: */
055: DeviceState deviceState = null;
056:
057: /**
058: * if this handler handles device, then keeps services available at it,
059: * else <code>null</code>.
060: */
061: Hashtable deviceServices = null;
062:
063: /**
064: * Keeps messenger that provides utilities for communicating with client.
065: */
066: private Messenger messenger = new Messenger();
067:
068: /** Keeps socket connection to the server. */
069: private SocketConnection connection;
070: /** Keeps input stream from server. */
071: private InputStream fromClient;
072: /** Keeps output stream to server. */
073: private OutputStream toClient;
074:
075: /**
076: * Retrieves handle value for a new handler.
077: * @return new free handle value
078: */
079: private static synchronized int getNextHandle() {
080: return ++nextHandle;
081: }
082:
083: /**
084: * Constructs client handle to communicate with a client thru
085: * given connection.
086: * @param connection an open connection with a client on the other side
087: * @exception IOException if connection fails
088: */
089: ClientHandler(SocketConnection connection) throws Exception {
090: this .connection = connection;
091: fromClient = connection.openDataInputStream();
092: toClient = connection.openDataOutputStream();
093: handle = getNextHandle();
094:
095: Thread t = new Thread(this );
096: t.start();
097: }
098:
099: /**
100: * Implements <code>Runnable</code>, processes client's rquests.
101: */
102: public void run() {
103: Exception exception = null;
104:
105: try {
106: loop: while (true) {
107: messenger.receive(fromClient);
108:
109: switch (messenger.getCode()) {
110: case Messenger.REGISTER_DEVICE:
111: ipAddress = messenger.getBytes();
112:
113: deviceServices = new Hashtable();
114: // IMPL_NOTE: how it works against Push TCK tests?
115: // default device state: not discoverable
116: deviceState = new DeviceState();
117:
118: bluetoothAddress = EmulationServer.getInstance()
119: .registerDevice(deviceState);
120:
121: messenger.sendBytes(toClient, Messenger.REGISTERED,
122: bluetoothAddress);
123:
124: break;
125:
126: case Messenger.UPDATE_DEVICE_STATE:
127: deviceState.update(messenger.getInt());
128: break;
129:
130: case Messenger.REGISTER_SERVICE:
131: ServiceConnectionData serv = new ServiceConnectionData(
132: messenger.getBytes(),
133: ServiceConnectionData.SERVER_DATA);
134: serv.address = ipAddress;
135:
136: ServiceKey key = EmulationServer.getInstance()
137: .registerService(serv, bluetoothAddress);
138:
139: if (!deviceServices.containsKey(key)) {
140: deviceServices.put(
141: new Integer(serv.socketPort), key);
142: }
143: break;
144:
145: case Messenger.UNREGISTER_SERVICE:
146: key = (ServiceKey) deviceServices
147: .remove(new Integer(messenger.getInt()));
148:
149: if (key != null) {
150: EmulationServer.getInstance()
151: .unregisterService(key);
152: key = null;
153: }
154: break;
155:
156: case Messenger.CONNECT_TO_SERVICE:
157: serv = EmulationServer
158: .getInstance()
159: .connectToService(
160: new ServiceConnectionData(
161: messenger.getBytes(),
162: ServiceConnectionData.CONN_REQUEST_DATA));
163:
164: messenger
165: .sendBytes(
166: toClient,
167: Messenger.SERVICE_AT,
168: serv
169: .toByteArray(ServiceConnectionData.CONNECTION_DATA));
170:
171: break;
172:
173: case Messenger.START_INQUIRY:
174: InquiryResults results = EmulationServer
175: .getInstance().runInquiry(
176: messenger.getInt(),
177: bluetoothAddress);
178: messenger.sendBytes(toClient,
179: Messenger.INQUIRY_COMPLETED, results
180: .toByteArray());
181: break;
182:
183: case Messenger.DONE:
184: break loop;
185:
186: default:
187: throw new EmulationException(
188: "Unknown client request");
189: }
190: } // end of loop:
191:
192: } catch (EmulationException ee) {
193: exception = ee;
194: } catch (IOException e) {
195: exception = e;
196: } finally {
197: if (exception != null) {
198: try {
199: messenger.send(toClient, Messenger.ERROR, exception
200: .getMessage());
201: } catch (IOException e) {
202: // ignoring - stop handling anyway
203: }
204: }
205:
206: if (deviceState != null) {
207: EmulationServer.getInstance().unregisterDevice(
208: bluetoothAddress);
209:
210: Enumeration records = deviceServices.elements();
211: while (records.hasMoreElements()) {
212: EmulationServer.getInstance().unregisterService(
213: (ServiceKey) records.nextElement());
214: }
215: }
216: disconnect();
217: }
218: }
219:
220: /**
221: * Closes current socket connection.
222: */
223: private void disconnect() {
224: try {
225: connection.close();
226: toClient.close();
227: fromClient.close();
228: } catch (IOException e) {
229: // ignoring
230: }
231:
232: connection = null;
233: fromClient = null;
234: toClient = null;
235: }
236: }
|