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             if (socket != null) {
    141                 try {
    142                     socket.close();
    143                 } catch (IOException e2) {
    144                 }
    145             }
    146             throw new IOException("Could not connect to socket");
    147         } catch (IOException e) {
    148             if (socket != null) {
    149                 try {
    150                     socket.close();
    151                 } catch (IOException e2) {
    152                 }
    153             }
    154             throw new IOException("Failed to connect to socket");
    155         }
    156 
    157         synchronized (this) {
    158             mMessenger = messenger;
    159             mState = CONNECTED;
    160         }
    161     }
    162 
    163     public void close() {
    164         synchronized (this) {
    165             if (mMessenger != null) {
    166                try {
    167                    mMessenger.close();
    168                } catch (IOException e) {
    169                    // ignore
    170                } finally {
    171                    mMessenger = null;
    172                    mState = DISCONNECTED;
    173                }
    174             }
    175         }
    176     }
    177 }
    178