FileDocCategorySizeDatePackage
ConnectionEmul.javaAPI DocphoneME MR2 API (J2ME)22219Wed May 02 18:00:30 BST 2007com.sun.midp.jsr82emul

ConnectionEmul

public class ConnectionEmul extends EmulationClient implements EmulUnit
Emulates JSR 82 connection.

Fields Summary
ServiceConnectionData
serviceData
Options of service to connect to.
private Opener
opener
Opener object needed to perform open operation in a separate thread.
private javax.microedition.io.SocketConnection
socketConnection
Socket connection that emulates JSR82 one.
private Sender
sender
Protocol dependent data sener.
private Receiver
receiver
Protocol dependent data receiver.
public int
handle
Handle that identifies this connection emulation.
static final int
CONN_OPEN
Request code for Open operation.
static final int
CONN_CLOSE
Request code for Close operation.
static final int
CONN_INIT
Request code for Init operation.
static final int
CONN_SEND
Request code for Send operation.
static final int
CONN_RECEIVE
Request code for Receive operation.
Constructors Summary
public ConnectionEmul(ServiceConnectionData serviceData)
Constructs an instance at server side.

param
serviceData connection options passed by notifier that creates this connection.

        this(getHandle(serviceData.protocol));
        this.serviceData = serviceData;
    
public ConnectionEmul(int handle)
Constructs an instance with given handle. Handle is an integer value that identifies correspondence between connections in porting layer nd ConnectionEmul instances. In case of client side connection handle is already defined in native create_client() functions. In case of server side it is generated in another constructor.

param
handle handle receieved form native layer.

        this.handle = handle;
        ConnRegistry.getInstance().register(this.handle, this);
    
Methods Summary
public voidclose()
Close this connection emulation.

        if (opener != null) {
            opener.interrupt();
            opener = null;
        }
        
        if (sender != null) {
            sender.close();
            sender = null;
        }
        
        if (receiver != null) {
            receiver.close();
            receiver = null;
        }
        
        if (socketConnection != null) {
            try {
                socketConnection.close();
            } catch (IOException e) {
                // ignoring
            }
            socketConnection = null;
        }
       
        ConnRegistry.getInstance().unregister(handle);
    
private static native intgetHandle(int protocol)
Retrieves new handle for a newly created connection at server side.

param
protocol integer protocol identifier
return
integral handle for a newly created connection

private static native booleangetOutData(int handle, byte[] buf)
Retrieves bytes from output native buffer for sending.

param
handle this connection handle
param
buf buffer to copy data to, it is implied that exactly buf.length to be sent from the native buffer
return
true if there is data to be sent, false otherwise

public intgetReceiveMTU()
Returns actually established ReceiveMTU.

return
established ReceiveMTU.

        return serviceData.receiveMTU;
    
public java.lang.StringgetRemoteAddress()
Returns Bluetooth address of other side of this connection.

return
Bluetooth address of the other side

        return BluetoothUtils.getAddressString(serviceData.address);
    
public intgetTransmitMTU()
Returns actually established TransmitMTU.

return
established TransmitMTU.

        return serviceData.transmitMTU;
    
private static native voidnotifyOpen(int handle, boolean success, int receiveMTU, int transmitMTU)
Notifies porting layer on open operation completion.

param
handle this connection handle
param
success true if opened successfully, false otherwize
param
receiveMTU receiveMTU of L2CAP connection established, ignored for RFCOMM
param
transmitMTU transmitMTU of L2CAP connection established, ignored for RFCOMM

static native voidnotifyReceived(int handle, byte[] bytes, int len)
Notifies porting layer on receive operation completion.

param
handle connection handle
param
bytes bytes received
param
len amount of bytes received, Const.CONN_FAILURE if receiving failed, Const.CONN_ENDOF_INP if there is nothing to receive due reaching end of input stream.

static native voidnotifySent(int handle, int len)
Notifies porting layer on send operation completion.

param
handle connection handle
param
len amount of bytes sent, CONN_FAILURE if sending failed

public intopen()
Opens client-side connection. Requests connection with given client connection string from emulation server

return
handle value
exception
IOException if communication to emulation server or a service fails.

        ServiceConnectionData connData;
        
        connect();
        
        messenger.sendBytes(toServer, Messenger.CONNECT_TO_SERVICE, 
            serviceData.toByteArray(
            ServiceConnectionData.CONN_REQUEST_DATA));
        
        messenger.receive(fromServer);
        
        if (messenger.getCode() != Messenger.SERVICE_AT) {
            throw new EmulationException(
                "Unexpected emulation server response " + 
                messenger.getCode());
        }
            
        connData = new ServiceConnectionData(
            messenger.getBytes(), ServiceConnectionData.CONNECTION_DATA);
        
        // no need to communicate with emulation sever any more
        // since a direct connection is open
        disconnect();
        
        if (connData.error != -1) {
            throw new BluetoothConnectionException(connData.error);
        }
        
        // vice versa to server side properties
        serviceData.receiveMTU = connData.transmitMTU;
        serviceData.transmitMTU = connData.receiveMTU;
        
        // applying bitwise operation to get unsigned values from bytes
        socketConnection = (SocketConnection) 
            new com.sun.midp.io.j2me.socket.Protocol().openPrim(
                internalSecurityToken, "//" +
                    (connData.address[0] & 0xff) + "." +
                    (connData.address[1] & 0xff) + "." +
                    (connData.address[2] & 0xff) + "." +
                    (connData.address[3] & 0xff) +
                    ":" + connData.socketPort);
        
        connData.address = DeviceEmul.getLocalDeviceEmul().address;
        sender = Sender.create(socketConnection, 
                    serviceData.protocol, handle);
        
        // It is important to use blocking sender method here
        sender.plainSend(connData.toByteArray(
            ServiceConnectionData.CLIENT_DATA));
        
        return handle;
    
public intopen(javax.microedition.io.SocketConnection socketConnection)
Opens server-side connection, i.e. assigns this emulation with already open server-side socket connection.

param
socketConnection already open server-side socket connection.
return
handle value
exception
IOException if communication to emulation server or a service fails.

        
        this.socketConnection = socketConnection;
        
        receiver = Receiver.create(socketConnection, 
                    serviceData.protocol, handle);
        
        // Calling blocking method intentionally here
        ServiceConnectionData connData = new ServiceConnectionData(
            receiver.forceReceive(ServiceConnectionData.CLIENT_DATA_SIZE),
            ServiceConnectionData.CLIENT_DATA);
        
        serviceData.receiveMTU = connData.receiveMTU;
        serviceData.transmitMTU = connData.transmitMTU;
        serviceData.address = connData.address;
        
        return handle;
    
public voidprocess(BytePack request)
Processes request from porting layer to emulation.

param
request packed request to process

    
                      
        
        
        switch (request.extract()) {
        case CONN_OPEN:
            Log.log("Processing CONN_OPEN " + handle); 
            serviceData.address = request.extractBytes(Const.BTADDR_SIZE);
            serviceData.port = request.extractInt();
            opener = new Opener();
            opener.start();
            break;
            
        case CONN_CLOSE:
            Log.log("Processing CONN_CLOSE " + handle); 
            close();
            break;
        
        case CONN_INIT:
            Log.log("Processing CONN_INIT " + handle); 
            serviceData = new ServiceConnectionData(
                request.extractBytes(ServiceConnectionData.SERVER_DATA_SIZE),
                ServiceConnectionData.SERVER_DATA);
            break;
        
        case CONN_SEND:
            Log.log("Processing CONN_SEND " + handle); 
            send(request.extractInt());
            break;
        
        case CONN_RECEIVE:
            Log.log("Processing CONN_RECEIVE " + handle); 
            receive();
            break;
            
        default:
            Log.log("Processing CONN_UNKNOWN " + handle); 
            throw new EmulationException("Unknown connection request");
        }
    
private voidreceive()
Reads data from emulated connection.

        if (receiver == null) {
            receiver = Receiver.create(socketConnection, 
                    serviceData.protocol, handle);
        }
        
        receiver.receive();
    
private voidsend(int len)
Sends data to the other side of the emulated connection.

param
len amount of bytes to send; given amount of bytes are sent from output buffer.
exception
IOException if an I/O error occurs

        byte[] buf = new byte[len];
        
        if (getOutData(handle, buf)) {
            if (sender == null) {
                sender = Sender.create(socketConnection, 
                    serviceData.protocol, handle);
            }
            sender.send(buf);
        }
        
        buf = null;