android_frameworks_base/obex/javax/obex/ServerSession.java
Hemant Gupta 850758fb63 Bluetooth: OBEX: Don't close transport when obex is disconnected
Precondition: PTS 7.0

Usecase:
Execute test case TC_TG_CA_BI_02_C for AVRCP 1.6

Expectation:
Test case should pass

Observation:
Test case fails

Root cause:
Disconnection of OBEX from PTS leads to disconnection of transport
(initiated by DUT) leading to test case failure. Obex server was
unnecessary assuming that transport would be disconnected so was
informing registered users that transport has been disconnected,
which was leading to issues on new obex connect on same transport
channel from remote obex client

Fix:
Remove check to break out of loop after obex disconnection, as that is
already handled in case when read would return -1 in case transport
is closed.

Test: TC_TG_CA_BI_02_C can be passed after the patch.

Bug: 35590000
Change-Id: Ic1682ce77c07cf2e43da09dc95fff2214338f758
2017-05-03 19:37:18 +00:00

743 lines
28 KiB
Java

/*
* Copyright (C) 2015 The Android Open Source Project
* Copyright (c) 2015 Samsung LSI
* Copyright (c) 2008-2009, Motorola, Inc.
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* - Neither the name of the Motorola, Inc. nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
package javax.obex;
import android.util.Log;
import java.io.InputStream;
import java.io.IOException;
import java.io.OutputStream;
/**
* This class in an implementation of the OBEX ServerSession.
* @hide
*/
public final class ServerSession extends ObexSession implements Runnable {
private static final String TAG = "Obex ServerSession";
private static final boolean V = ObexHelper.VDBG;
private ObexTransport mTransport;
private InputStream mInput;
private OutputStream mOutput;
private ServerRequestHandler mListener;
private Thread mProcessThread;
private int mMaxPacketLength;
private boolean mClosed;
/**
* Creates new ServerSession.
* @param trans the connection to the client
* @param handler the event listener that will process requests
* @param auth the authenticator to use with this connection
* @throws IOException if an error occurred while opening the input and
* output streams
*/
public ServerSession(ObexTransport trans, ServerRequestHandler handler, Authenticator auth)
throws IOException {
mAuthenticator = auth;
mTransport = trans;
mInput = mTransport.openInputStream();
mOutput = mTransport.openOutputStream();
mListener = handler;
mMaxPacketLength = 256;
mClosed = false;
mProcessThread = new Thread(this);
mProcessThread.start();
}
/**
* Processes requests made to the server and forwards them to the
* appropriate event listener.
*/
public void run() {
try {
boolean done = false;
while (!done && !mClosed) {
if(V) Log.v(TAG, "Waiting for incoming request...");
int requestType = mInput.read();
if(V) Log.v(TAG, "Read request: " + requestType);
switch (requestType) {
case ObexHelper.OBEX_OPCODE_CONNECT:
handleConnectRequest();
break;
case ObexHelper.OBEX_OPCODE_DISCONNECT:
handleDisconnectRequest();
break;
case ObexHelper.OBEX_OPCODE_GET:
case ObexHelper.OBEX_OPCODE_GET_FINAL:
handleGetRequest(requestType);
break;
case ObexHelper.OBEX_OPCODE_PUT:
case ObexHelper.OBEX_OPCODE_PUT_FINAL:
handlePutRequest(requestType);
break;
case ObexHelper.OBEX_OPCODE_SETPATH:
handleSetPathRequest();
break;
case ObexHelper.OBEX_OPCODE_ABORT:
handleAbortRequest();
break;
case -1:
done = true;
break;
default:
/*
* Received a request type that is not recognized so I am
* just going to read the packet and send a not implemented
* to the client
*/
int length = mInput.read();
length = (length << 8) + mInput.read();
for (int i = 3; i < length; i++) {
mInput.read();
}
sendResponse(ResponseCodes.OBEX_HTTP_NOT_IMPLEMENTED, null);
}
}
} catch (NullPointerException e) {
Log.d(TAG, "Exception occured - ignoring", e);
} catch (Exception e) {
Log.d(TAG, "Exception occured - ignoring", e);
}
close();
}
/**
* Handles a ABORT request from a client. This method will read the rest of
* the request from the client. Assuming the request is valid, it will
* create a <code>HeaderSet</code> object to pass to the
* <code>ServerRequestHandler</code> object. After the handler processes the
* request, this method will create a reply message to send to the server.
*
* @throws IOException if an error occurred at the transport layer
*/
private void handleAbortRequest() throws IOException {
int code = ResponseCodes.OBEX_HTTP_OK;
HeaderSet request = new HeaderSet();
HeaderSet reply = new HeaderSet();
int length = mInput.read();
length = (length << 8) + mInput.read();
if (length > ObexHelper.getMaxRxPacketSize(mTransport)) {
code = ResponseCodes.OBEX_HTTP_REQ_TOO_LARGE;
} else {
for (int i = 3; i < length; i++) {
mInput.read();
}
code = mListener.onAbort(request, reply);
Log.v(TAG, "onAbort request handler return value- " + code);
code = validateResponseCode(code);
}
sendResponse(code, null);
}
/**
* Handles a PUT request from a client. This method will provide a
* <code>ServerOperation</code> object to the request handler. The
* <code>ServerOperation</code> object will handle the rest of the request.
* It will also send replies and receive requests until the final reply
* should be sent. When the final reply should be sent, this method will get
* the response code to use and send the reply. The
* <code>ServerOperation</code> object will always reply with a
* OBEX_HTTP_CONTINUE reply. It will only reply if further information is
* needed.
* @param type the type of request received; either 0x02 or 0x82
* @throws IOException if an error occurred at the transport layer
*/
private void handlePutRequest(int type) throws IOException {
ServerOperation op = new ServerOperation(this, mInput, type, mMaxPacketLength, mListener);
try {
int response = -1;
if ((op.finalBitSet) && !op.isValidBody()) {
response = validateResponseCode(mListener
.onDelete(op.requestHeader, op.replyHeader));
} else {
response = validateResponseCode(mListener.onPut(op));
}
if (response != ResponseCodes.OBEX_HTTP_OK && !op.isAborted) {
op.sendReply(response);
} else if (!op.isAborted) {
// wait for the final bit
while (!op.finalBitSet) {
op.sendReply(ResponseCodes.OBEX_HTTP_CONTINUE);
}
op.sendReply(response);
}
} catch (Exception e) {
/*To fix bugs in aborted cases,
*(client abort file transfer prior to the last packet which has the end of body header,
*internal error should not be sent because server has already replied with
*OK response in "sendReply")
*/
if(V) Log.d(TAG,"Exception occured - sending OBEX_HTTP_INTERNAL_ERROR reply",e);
if (!op.isAborted) {
sendResponse(ResponseCodes.OBEX_HTTP_INTERNAL_ERROR, null);
}
}
}
/**
* Handles a GET request from a client. This method will provide a
* <code>ServerOperation</code> object to the request handler. The
* <code>ServerOperation</code> object will handle the rest of the request.
* It will also send replies and receive requests until the final reply
* should be sent. When the final reply should be sent, this method will get
* the response code to use and send the reply. The
* <code>ServerOperation</code> object will always reply with a
* OBEX_HTTP_CONTINUE reply. It will only reply if further information is
* needed.
* @param type the type of request received; either 0x03 or 0x83
* @throws IOException if an error occurred at the transport layer
*/
private void handleGetRequest(int type) throws IOException {
ServerOperation op = new ServerOperation(this, mInput, type, mMaxPacketLength, mListener);
try {
int response = validateResponseCode(mListener.onGet(op));
if (!op.isAborted) {
op.sendReply(response);
}
} catch (Exception e) {
if(V) Log.d(TAG,"Exception occured - sending OBEX_HTTP_INTERNAL_ERROR reply",e);
sendResponse(ResponseCodes.OBEX_HTTP_INTERNAL_ERROR, null);
}
}
/**
* Send standard response.
* @param code the response code to send
* @param header the headers to include in the response
* @throws IOException if an IO error occurs
*/
public void sendResponse(int code, byte[] header) throws IOException {
int totalLength = 3;
byte[] data = null;
OutputStream op = mOutput;
if (op == null) {
return;
}
if (header != null) {
totalLength += header.length;
data = new byte[totalLength];
data[0] = (byte)code;
data[1] = (byte)(totalLength >> 8);
data[2] = (byte)totalLength;
System.arraycopy(header, 0, data, 3, header.length);
} else {
data = new byte[totalLength];
data[0] = (byte)code;
data[1] = (byte)0x00;
data[2] = (byte)totalLength;
}
op.write(data);
op.flush(); // TODO: Do we need to flush?
}
/**
* Handles a SETPATH request from a client. This method will read the rest
* of the request from the client. Assuming the request is valid, it will
* create a <code>HeaderSet</code> object to pass to the
* <code>ServerRequestHandler</code> object. After the handler processes the
* request, this method will create a reply message to send to the server
* with the response code provided.
* @throws IOException if an error occurred at the transport layer
*/
private void handleSetPathRequest() throws IOException {
int length;
int flags;
@SuppressWarnings("unused")
int constants;
int totalLength = 3;
byte[] head = null;
int code = -1;
int bytesReceived;
HeaderSet request = new HeaderSet();
HeaderSet reply = new HeaderSet();
length = mInput.read();
length = (length << 8) + mInput.read();
flags = mInput.read();
constants = mInput.read();
if (length > ObexHelper.getMaxRxPacketSize(mTransport)) {
code = ResponseCodes.OBEX_HTTP_REQ_TOO_LARGE;
totalLength = 3;
} else {
if (length > 5) {
byte[] headers = new byte[length - 5];
bytesReceived = mInput.read(headers);
while (bytesReceived != headers.length) {
bytesReceived += mInput.read(headers, bytesReceived, headers.length
- bytesReceived);
}
ObexHelper.updateHeaderSet(request, headers);
if (mListener.getConnectionId() != -1 && request.mConnectionID != null) {
mListener.setConnectionId(ObexHelper.convertToLong(request.mConnectionID));
} else {
mListener.setConnectionId(1);
}
// the Auth chan is initiated by the server, client sent back the authResp .
if (request.mAuthResp != null) {
if (!handleAuthResp(request.mAuthResp)) {
code = ResponseCodes.OBEX_HTTP_UNAUTHORIZED;
mListener.onAuthenticationFailure(ObexHelper.getTagValue((byte)0x01,
request.mAuthResp));
}
request.mAuthResp = null;
}
}
if (code != ResponseCodes.OBEX_HTTP_UNAUTHORIZED) {
// the Auth challenge is initiated by the client
// the server will send back the authResp to the client
if (request.mAuthChall != null) {
handleAuthChall(request);
reply.mAuthResp = new byte[request.mAuthResp.length];
System.arraycopy(request.mAuthResp, 0, reply.mAuthResp, 0,
reply.mAuthResp.length);
request.mAuthChall = null;
request.mAuthResp = null;
}
boolean backup = false;
boolean create = true;
if (!((flags & 1) == 0)) {
backup = true;
}
if (!((flags & 2) == 0)) {
create = false;
}
try {
code = mListener.onSetPath(request, reply, backup, create);
} catch (Exception e) {
if(V) Log.d(TAG,"Exception occured - sending OBEX_HTTP_INTERNAL_ERROR reply",e);
sendResponse(ResponseCodes.OBEX_HTTP_INTERNAL_ERROR, null);
return;
}
code = validateResponseCode(code);
if (reply.nonce != null) {
mChallengeDigest = new byte[16];
System.arraycopy(reply.nonce, 0, mChallengeDigest, 0, 16);
} else {
mChallengeDigest = null;
}
long id = mListener.getConnectionId();
if (id == -1) {
reply.mConnectionID = null;
} else {
reply.mConnectionID = ObexHelper.convertToByteArray(id);
}
head = ObexHelper.createHeader(reply, false);
totalLength += head.length;
if (totalLength > mMaxPacketLength) {
totalLength = 3;
head = null;
code = ResponseCodes.OBEX_HTTP_INTERNAL_ERROR;
}
}
}
// Compute Length of OBEX SETPATH packet
byte[] replyData = new byte[totalLength];
replyData[0] = (byte)code;
replyData[1] = (byte)(totalLength >> 8);
replyData[2] = (byte)totalLength;
if (head != null) {
System.arraycopy(head, 0, replyData, 3, head.length);
}
/*
* Write the OBEX SETPATH packet to the server. Byte 0: response code
* Byte 1&2: Connect Packet Length Byte 3 to n: headers
*/
mOutput.write(replyData);
mOutput.flush();
}
/**
* Handles a disconnect request from a client. This method will read the
* rest of the request from the client. Assuming the request is valid, it
* will create a <code>HeaderSet</code> object to pass to the
* <code>ServerRequestHandler</code> object. After the handler processes the
* request, this method will create a reply message to send to the server.
* @throws IOException if an error occurred at the transport layer
*/
private void handleDisconnectRequest() throws IOException {
int length;
int code = ResponseCodes.OBEX_HTTP_OK;
int totalLength = 3;
byte[] head = null;
int bytesReceived;
HeaderSet request = new HeaderSet();
HeaderSet reply = new HeaderSet();
length = mInput.read();
length = (length << 8) + mInput.read();
if (length > ObexHelper.getMaxRxPacketSize(mTransport)) {
code = ResponseCodes.OBEX_HTTP_REQ_TOO_LARGE;
totalLength = 3;
} else {
if (length > 3) {
byte[] headers = new byte[length - 3];
bytesReceived = mInput.read(headers);
while (bytesReceived != headers.length) {
bytesReceived += mInput.read(headers, bytesReceived, headers.length
- bytesReceived);
}
ObexHelper.updateHeaderSet(request, headers);
}
if (mListener.getConnectionId() != -1 && request.mConnectionID != null) {
mListener.setConnectionId(ObexHelper.convertToLong(request.mConnectionID));
} else {
mListener.setConnectionId(1);
}
if (request.mAuthResp != null) {
if (!handleAuthResp(request.mAuthResp)) {
code = ResponseCodes.OBEX_HTTP_UNAUTHORIZED;
mListener.onAuthenticationFailure(ObexHelper.getTagValue((byte)0x01,
request.mAuthResp));
}
request.mAuthResp = null;
}
if (code != ResponseCodes.OBEX_HTTP_UNAUTHORIZED) {
if (request.mAuthChall != null) {
handleAuthChall(request);
request.mAuthChall = null;
}
try {
mListener.onDisconnect(request, reply);
} catch (Exception e) {
if(V) Log.d(TAG,"Exception occured - sending OBEX_HTTP_INTERNAL_ERROR reply",e);
sendResponse(ResponseCodes.OBEX_HTTP_INTERNAL_ERROR, null);
return;
}
long id = mListener.getConnectionId();
if (id == -1) {
reply.mConnectionID = null;
} else {
reply.mConnectionID = ObexHelper.convertToByteArray(id);
}
head = ObexHelper.createHeader(reply, false);
totalLength += head.length;
if (totalLength > mMaxPacketLength) {
totalLength = 3;
head = null;
code = ResponseCodes.OBEX_HTTP_INTERNAL_ERROR;
}
}
}
// Compute Length of OBEX CONNECT packet
byte[] replyData;
if (head != null) {
replyData = new byte[3 + head.length];
} else {
replyData = new byte[3];
}
replyData[0] = (byte)code;
replyData[1] = (byte)(totalLength >> 8);
replyData[2] = (byte)totalLength;
if (head != null) {
System.arraycopy(head, 0, replyData, 3, head.length);
}
/*
* Write the OBEX DISCONNECT packet to the server. Byte 0: response code
* Byte 1&2: Connect Packet Length Byte 3 to n: headers
*/
mOutput.write(replyData);
mOutput.flush();
}
/**
* Handles a connect request from a client. This method will read the rest
* of the request from the client. Assuming the request is valid, it will
* create a <code>HeaderSet</code> object to pass to the
* <code>ServerRequestHandler</code> object. After the handler processes the
* request, this method will create a reply message to send to the server
* with the response code provided.
* @throws IOException if an error occurred at the transport layer
*/
private void handleConnectRequest() throws IOException {
int packetLength;
@SuppressWarnings("unused")
int version;
@SuppressWarnings("unused")
int flags;
int totalLength = 7;
byte[] head = null;
int code = -1;
HeaderSet request = new HeaderSet();
HeaderSet reply = new HeaderSet();
int bytesReceived;
if(V) Log.v(TAG,"handleConnectRequest()");
/*
* Read in the length of the OBEX packet, OBEX version, flags, and max
* packet length
*/
packetLength = mInput.read();
packetLength = (packetLength << 8) + mInput.read();
if(V) Log.v(TAG,"handleConnectRequest() - packetLength: " + packetLength);
version = mInput.read();
flags = mInput.read();
mMaxPacketLength = mInput.read();
mMaxPacketLength = (mMaxPacketLength << 8) + mInput.read();
if(V) Log.v(TAG,"handleConnectRequest() - version: " + version
+ " MaxLength: " + mMaxPacketLength + " flags: " + flags);
// should we check it?
if (mMaxPacketLength > ObexHelper.MAX_PACKET_SIZE_INT) {
mMaxPacketLength = ObexHelper.MAX_PACKET_SIZE_INT;
}
if(mMaxPacketLength > ObexHelper.getMaxTxPacketSize(mTransport)) {
Log.w(TAG, "Requested MaxObexPacketSize " + mMaxPacketLength
+ " is larger than the max size supported by the transport: "
+ ObexHelper.getMaxTxPacketSize(mTransport)
+ " Reducing to this size.");
mMaxPacketLength = ObexHelper.getMaxTxPacketSize(mTransport);
}
if (packetLength > ObexHelper.getMaxRxPacketSize(mTransport)) {
code = ResponseCodes.OBEX_HTTP_REQ_TOO_LARGE;
totalLength = 7;
} else {
if (packetLength > 7) {
byte[] headers = new byte[packetLength - 7];
bytesReceived = mInput.read(headers);
while (bytesReceived != headers.length) {
bytesReceived += mInput.read(headers, bytesReceived, headers.length
- bytesReceived);
}
ObexHelper.updateHeaderSet(request, headers);
}
if (mListener.getConnectionId() != -1 && request.mConnectionID != null) {
mListener.setConnectionId(ObexHelper.convertToLong(request.mConnectionID));
} else {
mListener.setConnectionId(1);
}
if (request.mAuthResp != null) {
if (!handleAuthResp(request.mAuthResp)) {
code = ResponseCodes.OBEX_HTTP_UNAUTHORIZED;
mListener.onAuthenticationFailure(ObexHelper.getTagValue((byte)0x01,
request.mAuthResp));
}
request.mAuthResp = null;
}
if (code != ResponseCodes.OBEX_HTTP_UNAUTHORIZED) {
if (request.mAuthChall != null) {
handleAuthChall(request);
reply.mAuthResp = new byte[request.mAuthResp.length];
System.arraycopy(request.mAuthResp, 0, reply.mAuthResp, 0,
reply.mAuthResp.length);
request.mAuthChall = null;
request.mAuthResp = null;
}
try {
code = mListener.onConnect(request, reply);
code = validateResponseCode(code);
if (reply.nonce != null) {
mChallengeDigest = new byte[16];
System.arraycopy(reply.nonce, 0, mChallengeDigest, 0, 16);
} else {
mChallengeDigest = null;
}
long id = mListener.getConnectionId();
if (id == -1) {
reply.mConnectionID = null;
} else {
reply.mConnectionID = ObexHelper.convertToByteArray(id);
}
head = ObexHelper.createHeader(reply, false);
totalLength += head.length;
if (totalLength > mMaxPacketLength) {
totalLength = 7;
head = null;
code = ResponseCodes.OBEX_HTTP_INTERNAL_ERROR;
}
} catch (Exception e) {
if(V) Log.d(TAG,"Exception occured - sending OBEX_HTTP_INTERNAL_ERROR reply",e);
totalLength = 7;
head = null;
code = ResponseCodes.OBEX_HTTP_INTERNAL_ERROR;
}
}
}
// Compute Length of OBEX CONNECT packet
byte[] length = ObexHelper.convertToByteArray(totalLength);
/*
* Write the OBEX CONNECT packet to the server. Byte 0: response code
* Byte 1&2: Connect Packet Length Byte 3: OBEX Version Number
* (Presently, 0x10) Byte 4: Flags (For TCP 0x00) Byte 5&6: Max OBEX
* Packet Length (Defined in MAX_PACKET_SIZE) Byte 7 to n: headers
*/
byte[] sendData = new byte[totalLength];
int maxRxLength = ObexHelper.getMaxRxPacketSize(mTransport);
if (maxRxLength > mMaxPacketLength) {
if(V) Log.v(TAG,"Set maxRxLength to min of maxRxServrLen:" + maxRxLength +
" and MaxNegotiated from Client: " + mMaxPacketLength);
maxRxLength = mMaxPacketLength;
}
sendData[0] = (byte)code;
sendData[1] = length[2];
sendData[2] = length[3];
sendData[3] = (byte)0x10;
sendData[4] = (byte)0x00;
sendData[5] = (byte)(maxRxLength >> 8);
sendData[6] = (byte)(maxRxLength & 0xFF);
if (head != null) {
System.arraycopy(head, 0, sendData, 7, head.length);
}
mOutput.write(sendData);
mOutput.flush();
}
/**
* Closes the server session - in detail close I/O streams and the
* underlying transport layer. Internal flag is also set so that later
* attempt to read/write will throw an exception.
*/
public synchronized void close() {
if (mListener != null) {
mListener.onClose();
}
try {
/* Set state to closed before interrupting the thread by closing the streams */
mClosed = true;
if(mInput != null)
mInput.close();
if(mOutput != null)
mOutput.close();
if(mTransport != null)
mTransport.close();
} catch (Exception e) {
if(V) Log.d(TAG,"Exception occured during close() - ignore",e);
}
mTransport = null;
mInput = null;
mOutput = null;
mListener = null;
}
/**
* Verifies that the response code is valid. If it is not valid, it will
* return the <code>OBEX_HTTP_INTERNAL_ERROR</code> response code.
* @param code the response code to check
* @return the valid response code or <code>OBEX_HTTP_INTERNAL_ERROR</code>
* if <code>code</code> is not valid
*/
private int validateResponseCode(int code) {
if ((code >= ResponseCodes.OBEX_HTTP_OK) && (code <= ResponseCodes.OBEX_HTTP_PARTIAL)) {
return code;
}
if ((code >= ResponseCodes.OBEX_HTTP_MULT_CHOICE)
&& (code <= ResponseCodes.OBEX_HTTP_USE_PROXY)) {
return code;
}
if ((code >= ResponseCodes.OBEX_HTTP_BAD_REQUEST)
&& (code <= ResponseCodes.OBEX_HTTP_UNSUPPORTED_TYPE)) {
return code;
}
if ((code >= ResponseCodes.OBEX_HTTP_INTERNAL_ERROR)
&& (code <= ResponseCodes.OBEX_HTTP_VERSION)) {
return code;
}
if ((code >= ResponseCodes.OBEX_DATABASE_FULL)
&& (code <= ResponseCodes.OBEX_DATABASE_LOCKED)) {
return code;
}
return ResponseCodes.OBEX_HTTP_INTERNAL_ERROR;
}
public ObexTransport getTransport() {
return mTransport;
}
}