• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 DEFAULT_MIU = 128;
33     private static final int DEFAULT_RWSIZE = 1;
34     SnepMessenger mMessenger = null;
35     private final Object mTransmissionLock = new Object();
36 
37     private final String mServiceName;
38     private final int mPort;
39     private int  mState = DISCONNECTED;
40     private final int mAcceptableLength;
41     private final int mFragmentLength;
42     private final int mMiu;
43     private final int mRwSize;
44 
45     private static final int DISCONNECTED = 0;
46     private static final int CONNECTING = 1;
47     private static final int CONNECTED = 2;
48 
SnepClient()49     public SnepClient() {
50         mServiceName = SnepServer.DEFAULT_SERVICE_NAME;
51         mPort = SnepServer.DEFAULT_PORT;
52         mAcceptableLength = DEFAULT_ACCEPTABLE_LENGTH;
53         mFragmentLength = -1;
54         mMiu = DEFAULT_MIU;
55         mRwSize = DEFAULT_RWSIZE;
56     }
57 
SnepClient(String serviceName)58     public SnepClient(String serviceName) {
59         mServiceName = serviceName;
60         mPort = -1;
61         mAcceptableLength = DEFAULT_ACCEPTABLE_LENGTH;
62         mFragmentLength = -1;
63         mMiu = DEFAULT_MIU;
64         mRwSize = DEFAULT_RWSIZE;
65     }
66 
SnepClient(int miu, int rwSize)67     public SnepClient(int miu, int rwSize) {
68         mServiceName = SnepServer.DEFAULT_SERVICE_NAME;
69         mPort = SnepServer.DEFAULT_PORT;
70         mAcceptableLength = DEFAULT_ACCEPTABLE_LENGTH;
71         mFragmentLength = -1;
72         mMiu = miu;
73         mRwSize = rwSize;
74     }
75 
SnepClient(String serviceName, int fragmentLength)76     SnepClient(String serviceName, int fragmentLength) {
77         mServiceName = serviceName;
78         mPort = -1;
79         mAcceptableLength = DEFAULT_ACCEPTABLE_LENGTH;
80         mFragmentLength = fragmentLength;
81         mMiu = DEFAULT_MIU;
82         mRwSize = DEFAULT_RWSIZE;
83     }
84 
SnepClient(String serviceName, int acceptableLength, int fragmentLength)85     SnepClient(String serviceName, int acceptableLength, int fragmentLength) {
86         mServiceName = serviceName;
87         mPort = -1;
88         mAcceptableLength = acceptableLength;
89         mFragmentLength = fragmentLength;
90         mMiu = DEFAULT_MIU;
91         mRwSize = DEFAULT_RWSIZE;
92     }
93 
put(NdefMessage msg)94     public void put(NdefMessage msg) throws IOException {
95         SnepMessenger messenger;
96         synchronized (this) {
97             if (mState != CONNECTED) {
98                 throw new IOException("Socket not connected.");
99             }
100             messenger = mMessenger;
101         }
102 
103         synchronized (mTransmissionLock) {
104             try {
105                 messenger.sendMessage(SnepMessage.getPutRequest(msg));
106                 messenger.getMessage();
107             } catch (SnepException e) {
108                 throw new IOException(e);
109             }
110         }
111     }
112 
get(NdefMessage msg)113     public SnepMessage get(NdefMessage msg) throws IOException {
114         SnepMessenger messenger;
115         synchronized (this) {
116             if (mState != CONNECTED) {
117                 throw new IOException("Socket not connected.");
118             }
119             messenger = mMessenger;
120         }
121 
122         synchronized (mTransmissionLock) {
123             try {
124                 messenger.sendMessage(SnepMessage.getGetRequest(mAcceptableLength, msg));
125                 return messenger.getMessage();
126             } catch (SnepException e) {
127                 throw new IOException(e);
128             }
129         }
130     }
131 
connect()132     public void connect() throws IOException {
133         synchronized (this) {
134             if (mState != DISCONNECTED) {
135                 throw new IOException("Socket already in use.");
136             }
137             mState = CONNECTING;
138         }
139 
140         LlcpSocket socket = null;
141         SnepMessenger messenger;
142         try {
143             if (DBG) Log.d(TAG, "about to create socket");
144             // Connect to the snep server on the remote side
145             socket = NfcService.getInstance().createLlcpSocket(0, mMiu, mRwSize, 1024);
146             if (socket == null) {
147                 throw new IOException("Could not connect to socket.");
148             }
149             if (mPort == -1) {
150                 if (DBG) Log.d(TAG, "about to connect to service " + mServiceName);
151                 socket.connectToService(mServiceName);
152             } else {
153                 if (DBG) Log.d(TAG, "about to connect to port " + mPort);
154                 socket.connectToSap(mPort);
155             }
156             int miu = socket.getRemoteMiu();
157             int fragmentLength = (mFragmentLength == -1) ?  miu : Math.min(miu, mFragmentLength);
158             messenger = new SnepMessenger(true, socket, fragmentLength);
159         } catch (LlcpException e) {
160             synchronized (this) {
161                 mState = DISCONNECTED;
162             }
163             throw new IOException("Could not connect to socket");
164         } catch (IOException e) {
165             if (socket != null) {
166                 try {
167                     socket.close();
168                 } catch (IOException e2) {
169                 }
170             }
171             synchronized (this) {
172                 mState = DISCONNECTED;
173             }
174             throw new IOException("Failed to connect to socket");
175         }
176 
177         synchronized (this) {
178             mMessenger = messenger;
179             mState = CONNECTED;
180         }
181     }
182 
close()183     public void close() {
184         synchronized (this) {
185             if (mMessenger != null) {
186                try {
187                    mMessenger.close();
188                } catch (IOException e) {
189                    // ignore
190                } finally {
191                    mMessenger = null;
192                    mState = DISCONNECTED;
193                }
194             }
195         }
196     }
197 }
198