All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.intel.bluetooth.MicroeditionConnector Maven / Gradle / Ivy

/**
 *  BlueCove - Java library for Bluetooth
 *  Copyright (C) 2004 Intel Corporation
 *  Copyright (C) 2006-2007 Vlad Skarzhevskyy
 * 
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License as published by the Free Software Foundation; either
 *  version 2.1 of the License, or (at your option) any later version.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 *  @version $Id: MicroeditionConnector.java 1398 2007-12-19 19:16:52Z skarzhevskyy $
 */
package com.intel.bluetooth;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Enumeration;
import java.util.Hashtable;

import javax.bluetooth.BluetoothConnectionException;
import javax.bluetooth.L2CAPConnection;
import javax.bluetooth.UUID;
import javax.microedition.io.Connection;
import javax.microedition.io.ConnectionNotFoundException;
import javax.microedition.io.Connector;
import javax.microedition.io.InputConnection;
import javax.microedition.io.OutputConnection;

import com.intel.bluetooth.gcf.socket.ServerSocketConnection;
import com.intel.bluetooth.gcf.socket.SocketConnection;
import com.intel.bluetooth.obex.OBEXClientSessionImpl;
import com.intel.bluetooth.obex.OBEXConnectionParams;
import com.intel.bluetooth.obex.OBEXSessionNotifierImpl;

/**
 * 
 * Implementation of javax.microedition.io.Connector
 * 

* Your application should not use this class directly. */ public abstract class MicroeditionConnector { /* * Access mode READ. The value 1 is assigned to READ. */ public static final int READ = Connector.READ; /* * Access mode WRITE. The value 2 is assigned to WRITE. */ public static final int WRITE = Connector.WRITE; /* * Access mode READ_WRITE. The value 3 is assigned to READ_WRITE. */ public static final int READ_WRITE = Connector.READ_WRITE; private static Hashtable/* */suportScheme = new Hashtable(); private static Hashtable/* */srvParams = new Hashtable(); private static Hashtable/* */cliParams = new Hashtable(); private static Hashtable/* */cliParamsL2CAP = new Hashtable(); private static Hashtable/* */srvParamsL2CAP = new Hashtable(); private static final String AUTHENTICATE = "authenticate"; private static final String AUTHORIZE = "authorize"; private static final String ENCRYPT = "encrypt"; private static final String MASTER = "master"; private static final String NAME = "name"; private static final String RECEIVE_MTU = "receivemtu"; private static final String TRANSMIT_MTU = "transmitmtu"; private static final String EXT_BLUECOVE_L2CAP_PSM = "bluecovepsm"; static { // cliParams ::== master | encrypt | authenticate cliParams.put(AUTHENTICATE, AUTHENTICATE); cliParams.put(ENCRYPT, ENCRYPT); cliParams.put(MASTER, MASTER); // srvParams ::== name | master | encrypt | authorize | authenticate copyAll(srvParams, cliParams); srvParams.put(AUTHORIZE, AUTHORIZE); srvParams.put(NAME, NAME); copyAll(cliParamsL2CAP, cliParams); cliParamsL2CAP.put(RECEIVE_MTU, RECEIVE_MTU); cliParamsL2CAP.put(TRANSMIT_MTU, TRANSMIT_MTU); copyAll(srvParamsL2CAP, cliParamsL2CAP); srvParamsL2CAP.put(AUTHORIZE, AUTHORIZE); srvParamsL2CAP.put(NAME, NAME); srvParamsL2CAP.put(EXT_BLUECOVE_L2CAP_PSM, EXT_BLUECOVE_L2CAP_PSM); // "socket://" host ":" port // no validation for socket, since this is internal connector suportScheme.put(BluetoothConsts.PROTOCOL_SCHEME_RFCOMM, Boolean.TRUE); suportScheme.put(BluetoothConsts.PROTOCOL_SCHEME_BT_OBEX, Boolean.TRUE); suportScheme.put(BluetoothConsts.PROTOCOL_SCHEME_TCP_OBEX, Boolean.TRUE); suportScheme.put(BluetoothConsts.PROTOCOL_SCHEME_L2CAP, Boolean.TRUE); suportScheme.put("socket", Boolean.TRUE); } private MicroeditionConnector() { } static void copyAll(Hashtable dest, Hashtable src) { for (Enumeration en = src.keys(); en.hasMoreElements();) { Object key = en.nextElement(); dest.put(key, src.get(key)); } } static String validParamName(Hashtable map, String paramName) { String validName = (String) map.get(paramName.toLowerCase()); if (validName != null) { return validName; } return null; } /* * Create and open a Connection. Parameters: name - The URL for the * connection. Returns: A new Connection object. Throws: * IllegalArgumentException - If a parameter is invalid. * ConnectionNotFoundException - If the requested connection cannot be made, * or the protocol type does not exist. java.io.IOException - If some other * kind of I/O error occurs. SecurityException - If a requested protocol * handler is not permitted. */ public static Connection open(String name) throws IOException { return openImpl(name, READ_WRITE, false, true); } private static Connection openImpl(String name, int mode, boolean timeouts, boolean allowServer) throws IOException { DebugLog.debug("connecting", name); /* * parse URL */ String host = null; String portORuuid = null; Hashtable values = new Hashtable(); // scheme : // host : port [;param=val] int schemeEnd = name.indexOf("://"); if (schemeEnd == -1) { throw new ConnectionNotFoundException(name); } String scheme = name.substring(0, schemeEnd); if (!suportScheme.containsKey(scheme)) { throw new ConnectionNotFoundException(scheme); } boolean schemeBluetooth = (scheme.equals(BluetoothConsts.PROTOCOL_SCHEME_RFCOMM)) || (scheme.equals(BluetoothConsts.PROTOCOL_SCHEME_BT_OBEX) || (scheme .equals(BluetoothConsts.PROTOCOL_SCHEME_L2CAP))); boolean isL2CAP = scheme.equals(BluetoothConsts.PROTOCOL_SCHEME_L2CAP); boolean isTCPOBEX = scheme.equals(BluetoothConsts.PROTOCOL_SCHEME_TCP_OBEX); BluetoothStack bluetoothStack = null; if (schemeBluetooth) { bluetoothStack = BlueCoveImpl.instance().getBluetoothStack(); } boolean isServer; int hostEnd = name.indexOf(':', scheme.length() + 3); if (hostEnd > -1) { host = name.substring(scheme.length() + 3, hostEnd); isServer = host.equals("localhost"); Hashtable params; if (isTCPOBEX) { params = new Hashtable(); isServer = (host.length() == 0); } else if (isL2CAP) { if (isServer) { params = srvParamsL2CAP; } else { params = cliParamsL2CAP; } } else { if (isServer) { params = srvParams; } else { params = cliParams; } } String paramsStr = name.substring(hostEnd + 1); UtilsStringTokenizer tok = new UtilsStringTokenizer(paramsStr, ";"); if (tok.hasMoreTokens()) { portORuuid = tok.nextToken(); } else { portORuuid = paramsStr; } while (tok.hasMoreTokens()) { String t = tok.nextToken(); int equals = t.indexOf('='); if (equals > -1) { String param = t.substring(0, equals); String value = t.substring(equals + 1); String validName = validParamName(params, param); if (validName != null) { String hasValue = (String) values.get(validName); if ((hasValue != null) && (!hasValue.equals(value))) { throw new IllegalArgumentException("duplicate param [" + param + "] value [" + value + "]"); } values.put(validName, value); } else { throw new IllegalArgumentException("invalid param [" + param + "] value [" + value + "]"); } } else { throw new IllegalArgumentException("invalid param [" + t + "]"); } } } else if (isTCPOBEX) { host = name.substring(scheme.length() + 3); isServer = (host.length() == 0); } else { throw new IllegalArgumentException(name.substring(scheme.length() + 3)); } if (isTCPOBEX) { if ((portORuuid == null) || (portORuuid.length() == 0)) { portORuuid = String.valueOf(BluetoothConsts.TCP_OBEX_DEFAULT_PORT); } // else { // try { // int port = Integer.parseInt(portORuuid); // if ((port < 1023) && (port != // BluetoothConsts.TCP_OBEX_DEFAULT_PORT)) { // throw new IllegalArgumentException("Port " + portORuuid + " can't // be used; the 0-1023 range is reserved"); // } // } catch (NumberFormatException e) { // throw new IllegalArgumentException("port " + portORuuid); // } // } } if (host == null || portORuuid == null) { throw new IllegalArgumentException(); } BluetoothConnectionNotifierParams notifierParams = null; BluetoothConnectionParams connectionParams = null; int channel = 0; if (isServer) { if (!allowServer) { throw new IllegalArgumentException("Can't use server connection URL"); } if (values.get(NAME) == null) { values.put(NAME, "BlueCove"); } else if (schemeBluetooth) { validateBluetoothServiceName((String) values.get(NAME)); } if (schemeBluetooth) { notifierParams = new BluetoothConnectionNotifierParams(new UUID(portORuuid, false), paramBoolean( values, AUTHENTICATE), paramBoolean(values, ENCRYPT), paramBoolean(values, AUTHORIZE), (String) values.get(NAME), paramBoolean(values, MASTER)); notifierParams.timeouts = timeouts; if (notifierParams.encrypt && (!notifierParams.authenticate)) { if (values.get(AUTHENTICATE) == null) { notifierParams.authenticate = true; } else { throw new BluetoothConnectionException(BluetoothConnectionException.UNACCEPTABLE_PARAMS, "encryption requires authentication"); } } if (notifierParams.authorize && (!notifierParams.authenticate)) { if (values.get(AUTHENTICATE) == null) { notifierParams.authenticate = true; } else { throw new BluetoothConnectionException(BluetoothConnectionException.UNACCEPTABLE_PARAMS, "authorization requires authentication"); } } if (isL2CAP) { String bluecove_ext_psm = (String) values.get(EXT_BLUECOVE_L2CAP_PSM); if (bluecove_ext_psm != null) { int psm = Integer.parseInt(bluecove_ext_psm, 16); validateL2CAPPSM(psm, bluecove_ext_psm); notifierParams.bluecove_ext_psm = psm; } } } } else { // (!isServer) try { channel = Integer.parseInt(portORuuid, isL2CAP ? 16 : 10); } catch (NumberFormatException e) { throw new IllegalArgumentException("channel " + portORuuid); } if (channel < 0) { throw new IllegalArgumentException("channel " + portORuuid); } if (schemeBluetooth) { if (isL2CAP) { validateL2CAPPSM(channel, portORuuid); } else { if ((channel < BluetoothConsts.RFCOMM_CHANNEL_MIN) || (channel > BluetoothConsts.RFCOMM_CHANNEL_MAX)) { throw new IllegalArgumentException("RFCOMM channel " + portORuuid); } } connectionParams = new BluetoothConnectionParams(RemoteDeviceHelper.getAddress(host), channel, paramBoolean(values, AUTHENTICATE), paramBoolean(values, ENCRYPT)); connectionParams.timeouts = timeouts; if (connectionParams.encrypt && (!connectionParams.authenticate)) { if (values.get(AUTHENTICATE) == null) { connectionParams.authenticate = true; } else { throw new BluetoothConnectionException(BluetoothConnectionException.UNACCEPTABLE_PARAMS, "encryption requires authentication"); } } String timeout = BlueCoveImpl.getConfigProperty("bluecove.connect.timeout"); if (timeout != null) { connectionParams.timeout = Integer.parseInt(timeout); } } } OBEXConnectionParams obexConnectionParams = null; if (scheme.equals(BluetoothConsts.PROTOCOL_SCHEME_TCP_OBEX) || scheme.equals(BluetoothConsts.PROTOCOL_SCHEME_BT_OBEX)) { obexConnectionParams = new OBEXConnectionParams(); obexConnectionParams.timeouts = timeouts; String timeout = BlueCoveImpl.getConfigProperty("bluecove.obex.timeout"); if (timeout != null) { obexConnectionParams.timeout = Integer.parseInt(timeout); } String mtu = BlueCoveImpl.getConfigProperty("bluecove.obex.mtu"); if (mtu != null) { obexConnectionParams.mtu = Integer.parseInt(mtu); } } /* * create connection */ if (scheme.equals(BluetoothConsts.PROTOCOL_SCHEME_RFCOMM)) { if (isServer) { return new BluetoothRFCommConnectionNotifier(bluetoothStack, notifierParams); } else { return new BluetoothRFCommClientConnection(bluetoothStack, connectionParams); } } else if (scheme.equals(BluetoothConsts.PROTOCOL_SCHEME_BT_OBEX)) { if (isServer) { notifierParams.obex = true; return new OBEXSessionNotifierImpl( new BluetoothRFCommConnectionNotifier(bluetoothStack, notifierParams), obexConnectionParams); } else { return new OBEXClientSessionImpl(new BluetoothRFCommClientConnection(bluetoothStack, connectionParams), obexConnectionParams); } } else if (scheme.equals(BluetoothConsts.PROTOCOL_SCHEME_L2CAP)) { if (isServer) { return new BluetoothL2CAPConnectionNotifier(bluetoothStack, notifierParams, paramL2CAPMTU(values, RECEIVE_MTU), paramL2CAPMTU(values, TRANSMIT_MTU)); } else { return new BluetoothL2CAPClientConnection(bluetoothStack, connectionParams, paramL2CAPMTU(values, RECEIVE_MTU), paramL2CAPMTU(values, TRANSMIT_MTU)); } } else if (scheme.equals(BluetoothConsts.PROTOCOL_SCHEME_TCP_OBEX)) { if (isServer) { try { channel = Integer.parseInt(portORuuid); } catch (NumberFormatException e) { throw new IllegalArgumentException("port " + portORuuid); } return new OBEXSessionNotifierImpl(new ServerSocketConnection(channel), obexConnectionParams); } else { return new OBEXClientSessionImpl(new SocketConnection(host, channel), obexConnectionParams); } } else if (scheme.equals("socket")) { if (isServer) { try { channel = Integer.parseInt(portORuuid); } catch (NumberFormatException e) { throw new IllegalArgumentException("port " + portORuuid); } return new ServerSocketConnection(channel); } else { return new SocketConnection(host, channel); } } else { throw new ConnectionNotFoundException(scheme); } } private static void validateL2CAPPSM(int channel, String channelAsString) throws IllegalArgumentException { // Valid PSM range: 0x0001-0x0019 (0x1001-0xFFFF dynamically // assigned, 0x0019-0x0100 reserved for future use). if ((channel < BluetoothConsts.L2CAP_PSM_MIN) || (channel > BluetoothConsts.L2CAP_PSM_MAX)) { // PSM 1 discovery, 3 RFCOMM throw new IllegalArgumentException("PCM " + channelAsString); } // has the 9th bit (0x100) set to zero if ((channel & 0x100) != 0) { throw new IllegalArgumentException("9th bit set in PCM " + channelAsString); } if ((channel % 2) == 0) { throw new IllegalArgumentException("PSM value " + channelAsString + " should be odd"); } } private static void validateBluetoothServiceName(String serviceName) { if (serviceName.length() == 0) { throw new IllegalArgumentException("zero length service name"); } final String allowNameCharactes = " -_"; for (int i = 0; i < serviceName.length(); i++) { char c = serviceName.charAt(i); if ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || (c >= '0' && c <= '9') || allowNameCharactes.indexOf(c) != -1) { continue; } throw new IllegalArgumentException("Illegal character '" + c + "' in service name"); } } private static boolean paramBoolean(Hashtable values, String name) { String v = (String) values.get(name); if (v == null) { return false; } else if ("true".equals(v)) { return true; } else if ("false".equals(v)) { return false; } else { throw new IllegalArgumentException("invalid param value " + name + "=" + v); } } private static int paramL2CAPMTU(Hashtable values, String name) { String v = (String) values.get(name); if (v == null) { if (name.equals(TRANSMIT_MTU)) { // This will select RemoteMtu return -1; } else { return L2CAPConnection.DEFAULT_MTU; } } try { int mtu = Integer.parseInt(v); if (mtu >= L2CAPConnection.MINIMUM_MTU) { return mtu; } if ((mtu > 0) && (mtu < L2CAPConnection.MINIMUM_MTU) && (name.equals(TRANSMIT_MTU))) { return L2CAPConnection.MINIMUM_MTU; } } catch (NumberFormatException e) { throw new IllegalArgumentException("invalid MTU value " + v); } throw new IllegalArgumentException("invalid MTU param value " + name + "=" + v); } /* * Create and open a Connection. Parameters: name - The URL for the * connection. mode - The access mode. Returns: A new Connection object. * Throws: IllegalArgumentException - If a parameter is invalid. * ConnectionNotFoundException - If the requested connection cannot be made, * or the protocol type does not exist. java.io.IOException - If some other * kind of I/O error occurs. SecurityException - If a requested protocol * handler is not permitted. */ public static Connection open(String name, int mode) throws IOException { return openImpl(name, mode, false, true); } /* * Create and open a Connection. Parameters: name - The URL for the * connection mode - The access mode timeouts - A flag to indicate that the * caller wants timeout exceptions Returns: A new Connection object Throws: * IllegalArgumentException - If a parameter is invalid. * ConnectionNotFoundException - if the requested connection cannot be made, * or the protocol type does not exist. java.io.IOException - If some other * kind of I/O error occurs. SecurityException - If a requested protocol * handler is not permitted. */ public static Connection open(String name, int mode, boolean timeouts) throws IOException { return openImpl(name, mode, timeouts, true); } /* * Create and open a connection input stream. Parameters: name - The URL for * the connection. Returns: A DataInputStream. Throws: * IllegalArgumentException - If a parameter is invalid. * ConnectionNotFoundException - If the connection cannot be found. * java.io.IOException - If some other kind of I/O error occurs. * SecurityException - If access to the requested stream is not permitted. */ public static DataInputStream openDataInputStream(String name) throws IOException { return new DataInputStream(openInputStream(name)); } /* * Create and open a connection output stream. Parameters: name - The URL * for the connection. Returns: A DataOutputStream. Throws: * IllegalArgumentException - If a parameter is invalid. * ConnectionNotFoundException - If the connection cannot be found. * java.io.IOException - If some other kind of I/O error occurs. * SecurityException - If access to the requested stream is not permitted. */ public static DataOutputStream openDataOutputStream(String name) throws IOException { return new DataOutputStream(openOutputStream(name)); } /* * Create and open a connection input stream. Parameters: name - The URL for * the connection. Returns: An InputStream. Throws: IllegalArgumentException - * If a parameter is invalid. ConnectionNotFoundException - If the * connection cannot be found. java.io.IOException - If some other kind of * I/O error occurs. SecurityException - If access to the requested stream * is not permitted. */ public static InputStream openInputStream(String name) throws IOException { InputConnection con = ((InputConnection) openImpl(name, READ, false, false)); try { return con.openInputStream(); } finally { con.close(); } } /* * Create and open a connection output stream. Parameters: name - The URL * for the connection. Returns: An OutputStream. Throws: * IllegalArgumentException - If a parameter is invalid. * ConnectionNotFoundException - If the connection cannot be found. * java.io.IOException - If some other kind of I/O error occurs. * SecurityException - If access to the requested stream is not permitted. */ public static OutputStream openOutputStream(String name) throws IOException { OutputConnection con = ((OutputConnection) openImpl(name, WRITE, false, false)); try { return con.openOutputStream(); } finally { con.close(); } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy