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