/*
 * 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;
    }
}
