/*
 * 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();
                        done = true;
                        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);
        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;
    }
}
