Home | History | Annotate | Download | only in snep
      1 /*
      2  * Copyright (C) 2011 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.android.nfc.snep;
     18 
     19 import com.android.nfc.DeviceHost.LlcpSocket;
     20 import com.android.nfc.LlcpException;
     21 import com.android.nfc.NfcService;
     22 
     23 import android.nfc.NdefMessage;
     24 import android.util.Log;
     25 
     26 import java.io.IOException;
     27 
     28 public final class SnepClient {
     29     private static final String TAG = "SnepClient";
     30     private static final boolean DBG = false;
     31     private static final int DEFAULT_ACCEPTABLE_LENGTH = 100*1024;
     32     private static final int MIU = 128;
     33     SnepMessenger mMessenger = null;
     34     private final Object mTransmissionLock = new Object();
     35 
     36     private final String mServiceName;
     37     private final int mPort;
     38     private int  mState = DISCONNECTED;
     39     private final int mAcceptableLength;
     40     private final int mFragmentLength;
     41 
     42     private static final int DISCONNECTED = 0;
     43     private static final int CONNECTING = 1;
     44     private static final int CONNECTED = 2;
     45 
     46     public SnepClient() {
     47         mServiceName = SnepServer.DEFAULT_SERVICE_NAME;
     48         mPort = SnepServer.DEFAULT_PORT;
     49         mAcceptableLength = DEFAULT_ACCEPTABLE_LENGTH;
     50         mFragmentLength = -1;
     51     }
     52 
     53     public SnepClient(String serviceName) {
     54         mServiceName = serviceName;
     55         mPort = -1;
     56         mAcceptableLength = DEFAULT_ACCEPTABLE_LENGTH;
     57         mFragmentLength = -1;
     58     }
     59 
     60     SnepClient(String serviceName, int fragmentLength) {
     61         mServiceName = serviceName;
     62         mPort = -1;
     63         mAcceptableLength = DEFAULT_ACCEPTABLE_LENGTH;
     64         mFragmentLength = fragmentLength;
     65     }
     66 
     67     SnepClient(String serviceName, int acceptableLength, int fragmentLength) {
     68         mServiceName = serviceName;
     69         mPort = -1;
     70         mAcceptableLength = acceptableLength;
     71         mFragmentLength = fragmentLength;
     72     }
     73 
     74     public void put(NdefMessage msg) throws IOException {
     75         SnepMessenger messenger;
     76         synchronized (this) {
     77             if (mState != CONNECTED) {
     78                 throw new IOException("Socket not connected.");
     79             }
     80             messenger = mMessenger;
     81         }
     82 
     83         synchronized (mTransmissionLock) {
     84             try {
     85                 messenger.sendMessage(SnepMessage.getPutRequest(msg));
     86                 messenger.getMessage();
     87             } catch (SnepException e) {
     88                 throw new IOException(e);
     89             }
     90         }
     91     }
     92 
     93     public SnepMessage get(NdefMessage msg) throws IOException {
     94         SnepMessenger messenger;
     95         synchronized (this) {
     96             if (mState != CONNECTED) {
     97                 throw new IOException("Socket not connected.");
     98             }
     99             messenger = mMessenger;
    100         }
    101 
    102         synchronized (mTransmissionLock) {
    103             try {
    104                 messenger.sendMessage(SnepMessage.getGetRequest(mAcceptableLength, msg));
    105                 return messenger.getMessage();
    106             } catch (SnepException e) {
    107                 throw new IOException(e);
    108             }
    109         }
    110     }
    111 
    112     public void connect() throws IOException {
    113         synchronized (this) {
    114             if (mState != DISCONNECTED) {
    115                 throw new IOException("Socket already in use.");
    116             }
    117             mState = CONNECTING;
    118         }
    119 
    120         LlcpSocket socket = null;
    121         SnepMessenger messenger;
    122         try {
    123             if (DBG) Log.d(TAG, "about to create socket");
    124             // Connect to the snep server on the remote side
    125             socket = NfcService.getInstance().createLlcpSocket(0, MIU, 1, 1024);
    126             if (socket == null) {
    127                 throw new IOException("Could not connect to socket.");
    128             }
    129             if (mPort == -1) {
    130                 if (DBG) Log.d(TAG, "about to connect to service " + mServiceName);
    131                 socket.connectToService(mServiceName);
    132             } else {
    133                 if (DBG) Log.d(TAG, "about to connect to port " + mPort);
    134                 socket.connectToSap(mPort);
    135             }
    136             int miu = socket.getRemoteMiu();
    137             int fragmentLength = (mFragmentLength == -1) ?  miu : Math.min(miu, mFragmentLength);
    138             messenger = new SnepMessenger(true, socket, fragmentLength);
    139         } catch (LlcpException e) {
    140             throw new IOException("Could not connect to socket");
    141         } catch (IOException e) {
    142             if (socket != null) {
    143                 try {
    144                     socket.close();
    145                 } catch (IOException e2) {
    146                 }
    147             }
    148             throw new IOException("Failed to connect to socket");
    149         }
    150 
    151         synchronized (this) {
    152             mMessenger = messenger;
    153             mState = CONNECTED;
    154         }
    155     }
    156 
    157     public void close() {
    158         synchronized (this) {
    159             if (mMessenger != null) {
    160                try {
    161                    mMessenger.close();
    162                } catch (IOException e) {
    163                    // ignore
    164                } finally {
    165                    mMessenger = null;
    166                    mState = DISCONNECTED;
    167                }
    168             }
    169         }
    170     }
    171 }
    172