1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 package com.intel.bluetooth.obex;
22
23 import java.io.ByteArrayOutputStream;
24 import java.io.IOException;
25 import java.io.InputStream;
26 import java.io.OutputStream;
27
28 import javax.bluetooth.RemoteDevice;
29 import javax.bluetooth.ServiceRecord;
30 import javax.microedition.io.Connection;
31 import javax.microedition.io.StreamConnection;
32 import javax.obex.Authenticator;
33 import javax.obex.HeaderSet;
34 import javax.obex.ServerRequestHandler;
35
36 import com.intel.bluetooth.BluetoothConnectionAccess;
37 import com.intel.bluetooth.BluetoothStack;
38 import com.intel.bluetooth.DebugLog;
39
40
41
42
43
44
45
46
47
48 abstract class OBEXSessionBase implements Connection, BluetoothConnectionAccess {
49
50 protected StreamConnection conn;
51
52 protected InputStream is;
53
54 protected OutputStream os;
55
56 protected long connectionID;
57
58 protected int mtu = OBEXOperationCodes.OBEX_DEFAULT_MTU;
59
60 protected Authenticator authenticator;
61
62 protected OBEXConnectionParams obexConnectionParams;
63
64 protected int packetsCountWrite;
65
66 protected int packetsCountRead;
67
68 public OBEXSessionBase(StreamConnection conn, OBEXConnectionParams obexConnectionParams) throws IOException {
69 if (obexConnectionParams == null) {
70 throw new NullPointerException("obexConnectionParams is null");
71 }
72 this.conn = conn;
73 this.obexConnectionParams = obexConnectionParams;
74 this.mtu = obexConnectionParams.mtu;
75 this.connectionID = -1;
76 this.packetsCountWrite = 0;
77 this.packetsCountRead = 0;
78 boolean initOK = false;
79 try {
80 this.os = conn.openOutputStream();
81 this.is = conn.openInputStream();
82 initOK = true;
83 } finally {
84 if (!initOK) {
85 try {
86 this.close();
87 } catch (IOException e) {
88 DebugLog.error("close error", e);
89 }
90 }
91 }
92 }
93
94 public void close() throws IOException {
95 StreamConnection c = this.conn;
96 this.conn = null;
97 try {
98 if (this.is != null) {
99 this.is.close();
100 this.is = null;
101 }
102 if (this.os != null) {
103 this.os.close();
104 this.os = null;
105 }
106 } finally {
107 if (c != null) {
108 c.close();
109 }
110 }
111 }
112
113 public static HeaderSet createOBEXHeaderSet() {
114 return new OBEXHeaderSetImpl();
115 }
116
117 static void validateCreatedHeaderSet(HeaderSet headers) {
118 OBEXHeaderSetImpl.validateCreatedHeaderSet(headers);
119 }
120
121 protected void writeOperation(int commId, byte[] data) throws IOException {
122 writeOperation(commId, null, data);
123 }
124
125 protected void writeOperation(int commId, byte[] headerFlagsData, byte[] data) throws IOException {
126 int len = 3;
127 if (this.connectionID != -1) {
128 len += 5;
129 }
130 if (headerFlagsData != null) {
131 len += headerFlagsData.length;
132 }
133 if (data != null) {
134 len += data.length;
135 }
136 if (len > mtu) {
137 throw new IOException("Can't sent more data than in MTU, len=" + len + ", mtu=" + mtu);
138 }
139 this.packetsCountWrite++;
140 ByteArrayOutputStream buf = new ByteArrayOutputStream();
141 OBEXHeaderSetImpl.writeObexLen(buf, commId, len);
142 if (headerFlagsData != null) {
143 buf.write(headerFlagsData);
144 }
145 if (this.connectionID != -1) {
146 OBEXHeaderSetImpl.writeObexInt(buf, OBEXHeaderSetImpl.OBEX_HDR_CONNECTION, this.connectionID);
147 }
148 if (data != null) {
149 buf.write(data);
150 }
151 DebugLog.debug0x("obex send (" + this.packetsCountWrite + ")", OBEXUtils.toStringObexResponseCodes(commId),
152 commId);
153 os.write(buf.toByteArray());
154 os.flush();
155 DebugLog.debug("obex sent (" + this.packetsCountWrite + ") len", len);
156 }
157
158 protected byte[] readOperation() throws IOException {
159 byte[] header = new byte[3];
160 OBEXUtils.readFully(is, obexConnectionParams, header);
161 this.packetsCountRead++;
162 DebugLog.debug0x("obex received (" + this.packetsCountRead + ")", OBEXUtils
163 .toStringObexResponseCodes(header[0]), header[0] & 0xFF);
164 int lenght = OBEXUtils.bytesToShort(header[1], header[2]);
165 if (lenght == 3) {
166 return header;
167 }
168 if ((lenght < 3) || (lenght > OBEXOperationCodes.OBEX_MAX_PACKET_LEN)) {
169 throw new IOException("Invalid packet length " + lenght);
170 }
171 byte[] data = new byte[lenght];
172 System.arraycopy(header, 0, data, 0, header.length);
173 OBEXUtils.readFully(is, obexConnectionParams, data, header.length, lenght - header.length);
174 if (is.available() > 0) {
175 DebugLog.debug("has more data after read", is.available());
176 }
177 return data;
178 }
179
180 private void validateBluetoothConnection() {
181 if ((conn != null) && !(conn instanceof BluetoothConnectionAccess)) {
182 throw new IllegalArgumentException("Not a Bluetooth connection " + conn.getClass().getName());
183 }
184 }
185
186 void validateAuthenticationResponse(OBEXHeaderSetImpl requestHeaders, OBEXHeaderSetImpl incomingHeaders)
187 throws IOException {
188 if ((requestHeaders != null) && requestHeaders.hasAuthenticationChallenge()
189 && (!incomingHeaders.hasAuthenticationResponse())) {
190
191 throw new IOException("Authentication response is missing");
192 }
193 handleAuthenticationResponse(incomingHeaders, null);
194 }
195
196 void handleAuthenticationResponse(OBEXHeaderSetImpl incomingHeaders, ServerRequestHandler serverHandler)
197 throws IOException {
198 if (incomingHeaders.hasAuthenticationResponse()) {
199 if (authenticator == null) {
200 throw new IOException("Authenticator required for authentication");
201 }
202 OBEXAuthentication.handleAuthenticationResponse(incomingHeaders, authenticator, serverHandler);
203 }
204 }
205
206 void handleAuthenticationChallenge(OBEXHeaderSetImpl incomingHeaders, OBEXHeaderSetImpl replyHeaders)
207 throws IOException {
208 if (incomingHeaders.hasAuthenticationChallenge()) {
209 if (authenticator == null) {
210 throw new IOException("Authenticator required for authentication");
211 }
212 OBEXAuthentication.handleAuthenticationChallenge(incomingHeaders, replyHeaders, authenticator);
213 }
214 }
215
216
217
218
219
220
221 public long getRemoteAddress() throws IOException {
222 validateBluetoothConnection();
223 if (conn == null) {
224 throw new IOException("Connection closed");
225 }
226 return ((BluetoothConnectionAccess) conn).getRemoteAddress();
227 }
228
229
230
231
232
233
234 public RemoteDevice getRemoteDevice() {
235 validateBluetoothConnection();
236 if (conn == null) {
237 return null;
238 }
239 return ((BluetoothConnectionAccess) conn).getRemoteDevice();
240 }
241
242
243
244
245
246
247 public boolean isClosed() {
248 if (conn == null) {
249 return true;
250 }
251 if (this.conn instanceof BluetoothConnectionAccess) {
252 return ((BluetoothConnectionAccess) conn).isClosed();
253 } else {
254 return false;
255 }
256 }
257
258
259
260
261
262
263 public void shutdown() throws IOException {
264 if (this.conn instanceof BluetoothConnectionAccess) {
265 ((BluetoothConnectionAccess) conn).shutdown();
266 }
267 }
268
269
270
271
272
273
274 public void markAuthenticated() {
275 validateBluetoothConnection();
276 if (conn != null) {
277 ((BluetoothConnectionAccess) conn).markAuthenticated();
278 }
279 }
280
281
282
283
284
285
286 public int getSecurityOpt() {
287 validateBluetoothConnection();
288 if (conn == null) {
289 return ServiceRecord.NOAUTHENTICATE_NOENCRYPT;
290 } else {
291 return ((BluetoothConnectionAccess) conn).getSecurityOpt();
292 }
293 }
294
295
296
297
298
299
300 public boolean encrypt(long address, boolean on) throws IOException {
301 validateBluetoothConnection();
302 if (conn == null) {
303 throw new IOException("Connection closed");
304 }
305 return ((BluetoothConnectionAccess) conn).encrypt(address, on);
306 }
307
308
309
310
311
312
313 public void setRemoteDevice(RemoteDevice remoteDevice) {
314 validateBluetoothConnection();
315 if (conn != null) {
316 ((BluetoothConnectionAccess) conn).setRemoteDevice(remoteDevice);
317 }
318 }
319
320
321
322
323
324
325 public BluetoothStack getBluetoothStack() {
326 validateBluetoothConnection();
327 if (conn == null) {
328 return null;
329 }
330 return ((BluetoothConnectionAccess) conn).getBluetoothStack();
331 }
332
333
334
335
336
337
338 int getPacketsCountWrite() {
339 return this.packetsCountWrite;
340 }
341
342
343
344
345
346
347 int getPacketsCountRead() {
348 return this.packetsCountRead;
349 }
350
351
352
353
354
355
356 int getPacketSize() {
357 return this.mtu;
358 }
359 }