FileDocCategorySizeDatePackage
ConnectionManager.javaAPI DocJava Card7569Wed Mar 22 21:07:24 GMT 2006com.sun.javacard.samples.ChannelsDemo

ConnectionManager

public class ConnectionManager extends Applet implements ExtendedLength, MultiSelectable
This applet keeps track of the network connection for a fictional wireless device. Every time unit the device is being actively used on the network will result in decreasing credits available to the user. If the user changes areas, different charge rates applies. If the user runs out of credits, then the connection is terminated.

Fields Summary
static final byte
CM_CLA
static final byte
TIMETICK
static final byte
SETCONNECTION
static final byte
RESETCONNECTION
static final byte
VALIDATEKEY
static final short
INACTIVE_AREA
static final byte
CONNECTION_INUSE
static final byte
CONNECTION_FREE
static final short
SW_CONNECTION_BUSY
static final short
SW_NEGATIVE_BALANCE
static final short
SW_NO_NETWORK
static final short
SW_NO_ACCOUNT
static final short
SW_INVALID_KEY
private short[]
activeAreaCode
private byte[]
connectionStatus
Constructors Summary
private ConnectionManager(byte[] bArray, short bOffset, byte bLength)


            
        // The connection manager keeps track of the area where the 
        // device is operating.  Since the area changes as the user moves,
        // we keep track of the area by setting a variable in Transient
        // Clear-On-Deselect memory.
        activeAreaCode = 
            JCSystem.makeTransientShortArray((short)1, 
            JCSystem.CLEAR_ON_DESELECT);
        activeAreaCode[0] = INACTIVE_AREA;
        connectionStatus = 
            JCSystem.makeTransientByteArray((short)1, 
            JCSystem.CLEAR_ON_DESELECT);
        register();
    
Methods Summary
private voidclearState()

        activeAreaCode[0] = INACTIVE_AREA;
        connectionStatus[0] = CONNECTION_FREE;
    
public voiddeselect()

        clearState();
    
public voiddeselect(boolean appInstStillSelected)

        clearState();
    
private voidinitState()

        connectionStatus[0] = CONNECTION_FREE;
        activeAreaCode[0] = INACTIVE_AREA;
    
public static voidinstall(byte[] bArray, short bOffset, byte bLength)

        new ConnectionManager(bArray, bOffset, bLength);
    
public voidprocess(APDU apdu)

    
        byte[] buffer = apdu.getBuffer();
		
        if (apdu.isISOInterindustryCLA()) {
            if (buffer[ISO7816.OFFSET_INS] == (byte)(0xA4)) {
                return;
            } else {
                ISOException.throwIt (ISO7816.SW_CLA_NOT_SUPPORTED);
            }
        }
        
        switch (buffer[ISO7816.OFFSET_INS]) {
            case VALIDATEKEY:
                validateKey(apdu);
                return;
            case TIMETICK:      
                timeTick(apdu);
                return;
            case SETCONNECTION:
                setConnection();
                return;
            case RESETCONNECTION: 
                resetConnection();
                return;
            default:       
                ISOException.throwIt (ISO7816.SW_INS_NOT_SUPPORTED);
        }

    
private voidresetConnection()

        // Terminate the connection
        connectionStatus[0] = CONNECTION_FREE;
    
public booleanselect()

        initState();
        return true;
    
public booleanselect(boolean appInstAlreadySelected)

        // The connection manager can only be selected on one
        // logical channel. Reject selection if terminal tries
        // to select connection in more than one channel.
        if (appInstAlreadySelected) {
            // No more than 1 channel selection allowed
            return false;
        } else {
            initState();
            return true;
        }
    
private voidsetConnection()


        if (AccountAccessor.getAccount() == null) {
            ISOException.throwIt(SW_NO_ACCOUNT);
        }
        
        if (connectionStatus[0] == CONNECTION_INUSE) {
            ISOException.throwIt(SW_CONNECTION_BUSY);
        }
    
        if (activeAreaCode[0] == INACTIVE_AREA) {
            ISOException.throwIt(SW_NO_NETWORK);
        }
        
        // The first time unit is charged at connection setup
        if (AccountAccessor.getAccount().debit(activeAreaCode[0], false)) {
            connectionStatus[0] = CONNECTION_INUSE;
        } else {
           ISOException.throwIt(SW_NEGATIVE_BALANCE); 
        }        
    
private voidtimeTick(APDU apdu)

        // Updates the area code according to the passed parameter.
        byte[] buffer = apdu.getBuffer();
        byte numBytes = (byte)(buffer[ISO7816.OFFSET_LC]);
        byte byteRead = (byte)(apdu.setIncomingAndReceive());

        if ( ( numBytes != 2 ) || (byteRead != 2) )
        ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);

        // get area code
        short newAreaCode = (short)
            ((short)(buffer[ISO7816.OFFSET_CDATA] << (short)8) |
            (short)(buffer[ISO7816.OFFSET_CDATA + 1] & 0x00FF));
        
        if (newAreaCode != INACTIVE_AREA) {
            activeAreaCode[0] = newAreaCode;
        } else {
            resetConnection();
            ISOException.throwIt(SW_NO_NETWORK);
        }
        
        short connectionType = apdu.getProtocol();
        byte b = apdu.getCLAChannel();
        boolean contactless = false;
        if((connectionType & 0xf0) == 0x80//APDU.PROTOCOL_MEDIA_CONTACTLESS_TYPE_A 
            || (connectionType & 0xf0) ==  0x90){//APDU.PROTOCOL_MEDIA_CONTACTLESS_TYPE_B ){
            contactless = true;
        }
        
        // If a connection is active, the user account is debited.
        // If user runs out of credits, the connection is terminated.        
        if (connectionStatus[0] == CONNECTION_INUSE) {
            
            if (AccountAccessor.getAccount() == null) {
                ISOException.throwIt(SW_NO_ACCOUNT);
            }
            
            if (AccountAccessor.getAccount().debit(activeAreaCode[0], contactless) == false) {
                resetConnection();
                ISOException.throwIt(SW_NEGATIVE_BALANCE);
            }
        }
    
private voidvalidateKey(APDU apdu)

        //fake key test
        byte[] buffer = apdu.getBuffer();
        //process extended length apdu 
        short testKey = (short)((short)(buffer[ISO7816.OFFSET_EXT_CDATA] << (short)8) |
                        (short)(buffer[ISO7816.OFFSET_EXT_CDATA + 3] & 0x00FF));
        if(testKey != (short) 3)
            ISOException.throwIt(SW_INVALID_KEY);
        return;
        //System.out.println("here here");