/* 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 com.android.obex;

import android.util.Log;

import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

/**
 * This class implements the Operation interface for server side connections.
 * <P>
 * <STRONG>Request Codes</STRONG> There are four different request codes that
 * are in this class. 0x02 is a PUT request that signals that the request is not
 * complete and requires an additional OBEX packet. 0x82 is a PUT request that
 * says that request is complete. In this case, the server can begin sending the
 * response. The 0x03 is a GET request that signals that the request is not
 * finished. When the server receives a 0x83, the client is signaling the server
 * that it is done with its request. TODO: Extend the ClientOperation and reuse
 * the methods defined TODO: in that class.
 */
public final class ServerOperation implements Operation, BaseStream {

    private static final String TAG = "ServerOperation";

    private static final boolean V = ObexHelper.VDBG; // Verbose debugging

    private boolean mAborted;

    /** @hide */
    public HeaderSet requestHeader;

    /** @hide */
    public HeaderSet replyHeader;

    /** @hide */
    public boolean finalBitSet;

    private InputStream mInput;

    private ServerSession mParent;

    private int mMaxPacketLength;

    private int mResponseSize;

    private boolean mClosed;

    private boolean mGetOperation;

    private PrivateInputStream mPrivateInput;

    private PrivateOutputStream mPrivateOutput;

    private ObexTransport mTransport;

    private boolean mPrivateOutputOpen;

    private String mExceptionString;

    private ServerRequestHandler mListener;

    private boolean mRequestFinished;

    private boolean mHasBody;

    private boolean mSendBodyHeader = true;
    // Assume SRM disabled - needs to be explicit
    // enabled by client
    private boolean mSrmEnabled = false;
    // A latch - when triggered, there is not way back ;-)
    private boolean mSrmActive = false;
    // Set to true when a SRM enable response have been send
    private boolean mSrmResponseSent = false;
    // keep waiting until final-bit is received in request
    // to handle the case where the SRM enable header is in
    // a different OBEX packet than the SRMP header.
    private boolean mSrmWaitingForRemote = true;
    // Why should we wait? - currently not exposed to apps.
    private boolean mSrmLocalWait = false;

    /**
     * Creates new ServerOperation
     * @param p the parent that created this object
     * @param in the input stream to read from
     * @param request the initial request that was received from the client
     * @param maxSize the max packet size that the client will accept
     * @param listen the listener that is responding to the request
     * @throws IOException if an IO error occurs
     *
     * @hide
     */
    public ServerOperation(ServerSession p, InputStream in, int request, int maxSize,
            ServerRequestHandler listen) throws IOException {

        mAborted = false;
        mParent = p;
        mInput = in;
        mMaxPacketLength = maxSize;
        mClosed = false;
        requestHeader = new HeaderSet();
        replyHeader = new HeaderSet();
        mPrivateInput = new PrivateInputStream(this);
        mResponseSize = 3;
        mListener = listen;
        mRequestFinished = false;
        mPrivateOutputOpen = false;
        mHasBody = false;
        ObexPacket packet;
        mTransport = p.getTransport();

        /*
         * Determine if this is a PUT request
         */
        if ((request == ObexHelper.OBEX_OPCODE_PUT) ||
                (request == ObexHelper.OBEX_OPCODE_PUT_FINAL)) {
            /*
             * It is a PUT request.
             */
            mGetOperation = false;

            /*
             * Determine if the final bit is set
             */
            if ((request & ObexHelper.OBEX_OPCODE_FINAL_BIT_MASK) == 0) {
                finalBitSet = false;
            } else {
                finalBitSet = true;
                mRequestFinished = true;
            }
        } else if ((request == ObexHelper.OBEX_OPCODE_GET) ||
                (request == ObexHelper.OBEX_OPCODE_GET_FINAL)) {
            /*
             * It is a GET request.
             */
            mGetOperation = true;

            // For Get request, final bit set is decided by server side logic
            finalBitSet = false;

            if (request == ObexHelper.OBEX_OPCODE_GET_FINAL) {
                mRequestFinished = true;
            }
        } else {
            throw new IOException("ServerOperation can not handle such request");
        }

        packet = ObexPacket.read(request, mInput);

        /*
         * Determine if the packet length is larger than this device can receive
         */
        if (packet.mLength > ObexHelper.getMaxRxPacketSize(mTransport)) {
            mParent.sendResponse(ResponseCodes.OBEX_HTTP_REQ_TOO_LARGE, null);
            throw new IOException("Packet received was too large. Length: "
                    + packet.mLength + " maxLength: " + ObexHelper.getMaxRxPacketSize(mTransport));
        }

        /*
         * Determine if any headers were sent in the initial request
         */
        if (packet.mLength > 3) {
            if(!handleObexPacket(packet)) {
                return;
            }
            /* Don't Pre-Send continue when Remote requested for SRM
             * Let the Application confirm.
             */
            if (V) Log.v(TAG, "Get App confirmation if SRM ENABLED case: " + mSrmEnabled
                    + " not hasBody case: " + mHasBody);
            if (!mHasBody && !mSrmEnabled) {
                while ((!mGetOperation) && (!finalBitSet)) {
                    sendReply(ResponseCodes.OBEX_HTTP_CONTINUE);
                    if (mPrivateInput.available() > 0) {
                        break;
                    }
                }
            }
        }
        /* Don't Pre-Send continue when Remote requested for SRM
          * Let the Application confirm.
          */
        if (V) Log.v(TAG, "Get App confirmation if SRM ENABLED case: " + mSrmEnabled
            + " not finalPacket: " + finalBitSet + " not GETOp Case: " + mGetOperation);
        while ((!mSrmEnabled) && (!mGetOperation) && (!finalBitSet)
                && (mPrivateInput.available() == 0)) {
            sendReply(ResponseCodes.OBEX_HTTP_CONTINUE);
            if (mPrivateInput.available() > 0) {
                break;
            }
        }

        // wait for get request finished !!!!
        while (mGetOperation && !mRequestFinished) {
            sendReply(ResponseCodes.OBEX_HTTP_CONTINUE);
        }
    }

    /**
     * Parse headers and update member variables
     * @param packet the received obex packet
     * @return false for failing authentication - and a OBEX_HTTP_UNAUTHORIZED
     * response have been send. Else true.
     * @throws IOException
     */
    private boolean handleObexPacket(ObexPacket packet) throws IOException {
        byte[] body = updateRequestHeaders(packet);

        if (body != null) {
            mHasBody = true;
        }
        if (mListener.getConnectionId() != -1 && requestHeader.mConnectionID != null) {
            mListener.setConnectionId(ObexHelper
                    .convertToLong(requestHeader.mConnectionID));
        } else {
            mListener.setConnectionId(1);
        }

        if (requestHeader.mAuthResp != null) {
            if (!mParent.handleAuthResp(requestHeader.mAuthResp)) {
                mExceptionString = "Authentication Failed";
                mParent.sendResponse(ResponseCodes.OBEX_HTTP_UNAUTHORIZED, null);
                mClosed = true;
                requestHeader.mAuthResp = null;
                return false;
            }
            requestHeader.mAuthResp = null;
        }

        if (requestHeader.mAuthChall != null) {
            mParent.handleAuthChall(requestHeader);
            // send the auhtResp to the client
            replyHeader.mAuthResp = new byte[requestHeader.mAuthResp.length];
            System.arraycopy(requestHeader.mAuthResp, 0, replyHeader.mAuthResp, 0,
                    replyHeader.mAuthResp.length);
            requestHeader.mAuthResp = null;
            requestHeader.mAuthChall = null;
        }

        if (body != null) {
            mPrivateInput.writeBytes(body, 1);
        }
        return true;
    }

    /**
     * Update the request header set, and sniff on SRM headers to update local state.
     * @param data the OBEX packet data
     * @return any bytes in a body/end-of-body header returned by {@link ObexHelper.updateHeaderSet}
     * @throws IOException
     */
    private byte[] updateRequestHeaders(ObexPacket packet) throws IOException {
        byte[] body = null;
        if (packet.mPayload != null) {
            body = ObexHelper.updateHeaderSet(requestHeader, packet.mPayload);
        }
        Byte srmMode = (Byte)requestHeader.getHeader(HeaderSet.SINGLE_RESPONSE_MODE);
        if(mTransport.isSrmSupported() && srmMode != null
                && srmMode == ObexHelper.OBEX_SRM_ENABLE) {
            mSrmEnabled = true;
            if(V) Log.d(TAG,"SRM is now ENABLED (but not active) for this operation");
        }
        checkForSrmWait(packet.mHeaderId);
        if((!mSrmWaitingForRemote) && (mSrmEnabled)) {
            if(V) Log.d(TAG,"SRM is now ACTIVE for this operation");
            mSrmActive = true;
        }
        return body;
    }

    /**
     * Call this only when a complete request have been received.
     * (This is not optimal, but the current design is not really suited to
     * the way SRM is specified.)
     */
    private void checkForSrmWait(int headerId){
        if (mSrmEnabled && (headerId == ObexHelper.OBEX_OPCODE_GET
                || headerId == ObexHelper.OBEX_OPCODE_GET_FINAL
                || headerId == ObexHelper.OBEX_OPCODE_PUT)) {
            try {
                mSrmWaitingForRemote = false;
                Byte srmp = (Byte)requestHeader.getHeader(HeaderSet.SINGLE_RESPONSE_MODE_PARAMETER);
                if(srmp != null && srmp == ObexHelper.OBEX_SRMP_WAIT) {
                    mSrmWaitingForRemote = true;
                    // Clear the wait header, as the absents of the header when the final bit is set
                    // indicates don't wait.
                    requestHeader.setHeader(HeaderSet.SINGLE_RESPONSE_MODE_PARAMETER, null);
                }
            } catch (IOException e) {if(V){Log.w(TAG,"Exception while extracting header",e);}}
        }
    }

    /** @hide */
    public boolean isValidBody() {
        return mHasBody;
    }

    /**
     * Determines if the operation should continue or should wait. If it should
     * continue, this method will continue the operation.
     * @param sendEmpty if <code>true</code> then this will continue the
     *        operation even if no headers will be sent; if <code>false</code>
     *        then this method will only continue the operation if there are
     *        headers to send
     * @param inStream if<code>true</code> the stream is input stream, otherwise
     *        output stream
     * @return <code>true</code> if the operation was completed;
     *         <code>false</code> if no operation took place
     *
     * @hide
     */
    public synchronized boolean continueOperation(boolean sendEmpty, boolean inStream)
            throws IOException {
        if (!mGetOperation) {
            if (!finalBitSet) {
                if (sendEmpty) {
                    sendReply(ResponseCodes.OBEX_HTTP_CONTINUE);
                    return true;
                } else {
                    if ((mResponseSize > 3) || (mPrivateOutput.size() > 0)) {
                        sendReply(ResponseCodes.OBEX_HTTP_CONTINUE);
                        return true;
                    } else {
                        return false;
                    }
                }
            } else {
                return false;
            }
        } else {
            sendReply(ResponseCodes.OBEX_HTTP_CONTINUE);
            return true;
        }
    }

    /**
     * Sends a reply to the client. If the reply is a OBEX_HTTP_CONTINUE, it
     * will wait for a response from the client before ending unless SRM is active.
     * @param type the response code to send back to the client
     * @return <code>true</code> if the final bit was not set on the reply;
     *         <code>false</code> if no reply was received because the operation
     *         ended, an abort was received, the final bit was set in the
     *         reply or SRM is active.
     * @throws IOException if an IO error occurs
     *
     * @hide
     */
    public synchronized boolean sendReply(int type) throws IOException {
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        boolean skipSend = false;
        boolean skipReceive = false;
        boolean srmRespSendPending = false;

        long id = mListener.getConnectionId();
        if (id == -1) {
            replyHeader.mConnectionID = null;
        } else {
            replyHeader.mConnectionID = ObexHelper.convertToByteArray(id);
        }

        if(mSrmEnabled && !mSrmResponseSent) {
            // As we are not ensured that the SRM enable is in the first OBEX packet
            // We must check for each reply.
            if(V)Log.v(TAG, "mSrmEnabled==true, sending SRM enable response.");
            replyHeader.setHeader(HeaderSet.SINGLE_RESPONSE_MODE, (byte)ObexHelper.OBEX_SRM_ENABLE);
            srmRespSendPending = true;
        }

        if(mSrmEnabled && !mGetOperation && mSrmLocalWait) {
            replyHeader.setHeader(HeaderSet.SINGLE_RESPONSE_MODE, (byte)ObexHelper.OBEX_SRMP_WAIT);
        }

        byte[] headerArray = ObexHelper.createHeader(replyHeader, true); // This clears the headers
        int bodyLength = -1;
        int originalBodyLength = -1;

        if (mPrivateOutput != null) {
            bodyLength = mPrivateOutput.size();
            originalBodyLength = bodyLength;
        }

        if ((ObexHelper.BASE_PACKET_LENGTH + headerArray.length) > mMaxPacketLength) {

            int end = 0;
            int start = 0;

            while (end != headerArray.length) {
                end = ObexHelper.findHeaderEnd(headerArray, start, mMaxPacketLength
                        - ObexHelper.BASE_PACKET_LENGTH);
                if (end == -1) {

                    mClosed = true;

                    if (mPrivateInput != null) {
                        mPrivateInput.close();
                    }

                    if (mPrivateOutput != null) {
                        mPrivateOutput.close();
                    }
                    mParent.sendResponse(ResponseCodes.OBEX_HTTP_INTERNAL_ERROR, null);
                    throw new IOException("OBEX Packet exceeds max packet size");
                }
                byte[] sendHeader = new byte[end - start];
                System.arraycopy(headerArray, start, sendHeader, 0, sendHeader.length);

                mParent.sendResponse(type, sendHeader);
                start = end;
            }

            if (bodyLength > 0) {
                return true;
            } else {
                return false;
            }

        } else {
            out.write(headerArray);
        }

        // For Get operation: if response code is OBEX_HTTP_OK, then this is the
        // last packet; so set finalBitSet to true.
        if (mGetOperation && type == ResponseCodes.OBEX_HTTP_OK) {
            finalBitSet = true;
        }

        if(mSrmActive) {
            if(!mGetOperation && type == ResponseCodes.OBEX_HTTP_CONTINUE &&
                    mSrmResponseSent == true) {
                // we are in the middle of a SRM PUT operation, don't send a continue.
                skipSend = true;
            } else if(mGetOperation && mRequestFinished == false && mSrmResponseSent == true) {
                // We are still receiving the get request, receive, but don't send continue.
                skipSend = true;
            } else if(mGetOperation && mRequestFinished == true) {
                // All done receiving the GET request, send data to the client, without
                // expecting a continue.
                skipReceive = true;
            }
            if(V)Log.v(TAG, "type==" + type + " skipSend==" + skipSend
                    + " skipReceive==" + skipReceive);
        }
        if(srmRespSendPending) {
            if(V)Log.v(TAG,
                    "SRM Enabled (srmRespSendPending == true)- sending SRM Enable response");
            mSrmResponseSent = true;
        }

        if ((finalBitSet) || (headerArray.length < (mMaxPacketLength - 20))) {
            if (bodyLength > 0) {
                /*
                 * Determine if I can send the whole body or just part of
                 * the body.  Remember that there is the 3 bytes for the
                 * response message and 3 bytes for the header ID and length
                 */
                if (bodyLength > (mMaxPacketLength - headerArray.length - 6)) {
                    bodyLength = mMaxPacketLength - headerArray.length - 6;
                }

                byte[] body = mPrivateOutput.readBytes(bodyLength);

                /*
                 * Since this is a put request if the final bit is set or
                 * the output stream is closed we need to send the 0x49
                 * (End of Body) otherwise, we need to send 0x48 (Body)
                 */
                if ((finalBitSet) || (mPrivateOutput.isClosed())) {
                    if(mSendBodyHeader == true) {
                        out.write(0x49);
                        bodyLength += 3;
                        out.write((byte)(bodyLength >> 8));
                        out.write((byte)bodyLength);
                        out.write(body);
                    }
                } else {
                    if(mSendBodyHeader == true) {
                    out.write(0x48);
                    bodyLength += 3;
                    out.write((byte)(bodyLength >> 8));
                    out.write((byte)bodyLength);
                    out.write(body);
                    }
                }

            }
        }

        if ((finalBitSet) && (type == ResponseCodes.OBEX_HTTP_OK) && (originalBodyLength <= 0)) {
            if(mSendBodyHeader) {
                out.write(0x49);
                originalBodyLength = 3;
                out.write((byte)(originalBodyLength >> 8));
                out.write((byte)originalBodyLength);
            }
        }

        if(skipSend == false) {
            mResponseSize = 3;
            mParent.sendResponse(type, out.toByteArray());
        }

        if (type == ResponseCodes.OBEX_HTTP_CONTINUE) {

            if(mGetOperation && skipReceive) {
                // Here we need to check for and handle abort (throw an exception).
                // Any other signal received should be discarded silently (only on server side)
                checkSrmRemoteAbort();
            } else {
                // Receive and handle data (only send reply if !skipSend)
                // Read a complete OBEX Packet
                ObexPacket packet = ObexPacket.read(mInput);

                int headerId = packet.mHeaderId;
                if ((headerId != ObexHelper.OBEX_OPCODE_PUT)
                        && (headerId != ObexHelper.OBEX_OPCODE_PUT_FINAL)
                        && (headerId != ObexHelper.OBEX_OPCODE_GET)
                        && (headerId != ObexHelper.OBEX_OPCODE_GET_FINAL)) {

                    /*
                     * Determine if an ABORT was sent as the reply
                     */
                    if (headerId == ObexHelper.OBEX_OPCODE_ABORT) {
                        handleRemoteAbort();
                    } else {
                        // TODO:shall we send this if it occurs during SRM? Errata on the subject
                        mParent.sendResponse(ResponseCodes.OBEX_HTTP_BAD_REQUEST, null);
                        mClosed = true;
                        mExceptionString = "Bad Request Received";
                        throw new IOException("Bad Request Received");
                    }
                } else {

                    if ((headerId == ObexHelper.OBEX_OPCODE_PUT_FINAL)) {
                        finalBitSet = true;
                    } else if (headerId == ObexHelper.OBEX_OPCODE_GET_FINAL) {
                        mRequestFinished = true;
                    }

                    /*
                     * Determine if the packet length is larger than the negotiated packet size
                     */
                    if (packet.mLength > ObexHelper.getMaxRxPacketSize(mTransport)) {
                        mParent.sendResponse(ResponseCodes.OBEX_HTTP_REQ_TOO_LARGE, null);
                        throw new IOException("Packet received was too large");
                    }

                    /*
                     * Determine if any headers were sent in the initial request
                     */
                    if (packet.mLength > 3 || (mSrmEnabled && packet.mLength == 3)) {
                        if(handleObexPacket(packet) == false) {
                            return false;
                        }
                    }
                }

            }
            return true;
        } else {
            return false;
        }
    }

    /**
     * This method will look for an abort from the peer during a SRM transfer.
     * The function will not block if no data has been received from the remote device.
     * If data have been received, the function will block while reading the incoming
     * OBEX package.
     * An Abort request will be handled, and cause an IOException("Abort Received").
     * Other messages will be discarded silently as per GOEP specification.
     * @throws IOException if an abort request have been received.
     * TODO: I think this is an error in the specification. If we discard other messages,
     *       the peer device will most likely stall, as it will not receive the expected
     *       response for the message...
     *       I'm not sure how to understand "Receipt of invalid or unexpected SRM or SRMP
     *       header values shall be ignored by the receiving device."
     *       If any signal is received during an active SRM transfer it is unexpected regardless
     *       whether or not it contains SRM/SRMP headers...
     */
    private void checkSrmRemoteAbort() throws IOException {
        if(mInput.available() > 0) {
            ObexPacket packet = ObexPacket.read(mInput);
            /*
             * Determine if an ABORT was sent as the reply
             */
            if (packet.mHeaderId == ObexHelper.OBEX_OPCODE_ABORT) {
                handleRemoteAbort();
            } else {
                // TODO: should we throw an exception here anyway? - don't see how to
                //       ignore SRM/SRMP headers without ignoring the complete signal
                //       (in this particular case).
                Log.w(TAG, "Received unexpected request from client - discarding...\n"
                        + "   headerId: " + packet.mHeaderId + " length: " + packet.mLength);
            }
        }
    }

    private void handleRemoteAbort() throws IOException {
        /* TODO: To increase the speed of the abort operation in SRM, we need
         *       to be able to flush the L2CAP queue for the PSM in use.
         *       This could be implemented by introducing a control
         *       message to be send over the socket, that in the abort case
         *       could carry a flush command. */
        mParent.sendResponse(ResponseCodes.OBEX_HTTP_OK, null);
        mClosed = true;
        mAborted = true;
        mExceptionString = "Abort Received";
        throw new IOException("Abort Received");
    }

    /**
     * Sends an ABORT message to the server. By calling this method, the
     * corresponding input and output streams will be closed along with this
     * object.
     * @throws IOException if the transaction has already ended or if an OBEX
     *         server called this method
     *
     * @hide
     */
    public void abort() throws IOException {
        throw new IOException("Called from a server");
    }

    /**
     * Returns the headers that have been received during the operation.
     * Modifying the object returned has no effect on the headers that are sent
     * or retrieved.
     * @return the headers received during this <code>Operation</code>
     * @throws IOException if this <code>Operation</code> has been closed
     *
     * @hide
     */
    public HeaderSet getReceivedHeader() throws IOException {
        ensureOpen();
        return requestHeader;
    }

    /**
     * Specifies the headers that should be sent in the next OBEX message that
     * is sent.
     * @param headers the headers to send in the next message
     * @throws IOException if this <code>Operation</code> has been closed or the
     *         transaction has ended and no further messages will be exchanged
     * @throws IllegalArgumentException if <code>headers</code> was not created
     *         by a call to <code>ServerRequestHandler.createHeaderSet()</code>
     *
     * @hide
     */
    public void sendHeaders(HeaderSet headers) throws IOException {
        ensureOpen();

        if (headers == null) {
            throw new IOException("Headers may not be null");
        }

        int[] headerList = headers.getHeaderList();
        if (headerList != null) {
            for (int i = 0; i < headerList.length; i++) {
                replyHeader.setHeader(headerList[i], headers.getHeader(headerList[i]));
            }

        }
    }

    /**
     * Retrieves the response code retrieved from the server. Response codes are
     * defined in the <code>ResponseCodes</code> interface.
     * @return the response code retrieved from the server
     * @throws IOException if an error occurred in the transport layer during
     *         the transaction; if this method is called on a
     *         <code>HeaderSet</code> object created by calling
     *         <code>createHeaderSet</code> in a <code>ClientSession</code>
     *         object; if this is called from a server
     *
     * @hide
     */
    public int getResponseCode() throws IOException {
        throw new IOException("Called from a server");
    }

    /** @hide */
    public int getMaxPacketSize() {
        return mMaxPacketLength - 6 - getHeaderLength();
    }

    /** @hide */
    public int getHeaderLength() {
        long id = mListener.getConnectionId();
        if (id == -1) {
            replyHeader.mConnectionID = null;
        } else {
            replyHeader.mConnectionID = ObexHelper.convertToByteArray(id);
        }

        byte[] headerArray = ObexHelper.createHeader(replyHeader, false);

        return headerArray.length;
    }

    /**
     * Open and return an input stream for a connection.
     * @return an input stream
     * @throws IOException if an I/O error occurs
     *
     * @hide
     */
    public InputStream openInputStream() throws IOException {
        ensureOpen();
        return mPrivateInput;
    }

    /**
     * Open and return a data input stream for a connection.
     * @return an input stream
     * @throws IOException if an I/O error occurs
     *
     * @hide
     */
    public DataInputStream openDataInputStream() throws IOException {
        return new DataInputStream(openInputStream());
    }

    /**
     * Open and return an output stream for a connection.
     * @return an output stream
     * @throws IOException if an I/O error occurs
     *
     * @hide
     */
    public OutputStream openOutputStream() throws IOException {
        ensureOpen();

        if (mPrivateOutputOpen) {
            throw new IOException("no more input streams available, stream already opened");
        }

        if (!mRequestFinished) {
            throw new IOException("no  output streams available ,request not finished");
        }

        if (mPrivateOutput == null) {
            mPrivateOutput = new PrivateOutputStream(this, getMaxPacketSize());
        }
        mPrivateOutputOpen = true;
        return mPrivateOutput;
    }

    /**
     * Open and return a data output stream for a connection.
     * @return an output stream
     * @throws IOException if an I/O error occurs
     *
     * @hide
     */
    public DataOutputStream openDataOutputStream() throws IOException {
        return new DataOutputStream(openOutputStream());
    }

    /**
     * Closes the connection and ends the transaction
     * @throws IOException if the operation has already ended or is closed
     *
     * @hide
     */
    public void close() throws IOException {
        ensureOpen();
        mClosed = true;
    }

    /**
     * Verifies that the connection is open and no exceptions should be thrown.
     * @throws IOException if an exception needs to be thrown
     *
     * @hide
     */
    public void ensureOpen() throws IOException {
        if (mExceptionString != null) {
            throw new IOException(mExceptionString);
        }
        if (mClosed) {
            throw new IOException("Operation has already ended");
        }
    }

    /**
     * Verifies that additional information may be sent. In other words, the
     * operation is not done.
     * <P>
     * Included to implement the BaseStream interface only. It does not do
     * anything on the server side since the operation of the Operation object
     * is not done until after the handler returns from its method.
     * @throws IOException if the operation is completed
     *
     * @hide
     */
    public void ensureNotDone() throws IOException {
    }

    /**
     * Called when the output or input stream is closed. It does not do anything
     * on the server side since the operation of the Operation object is not
     * done until after the handler returns from its method.
     * @param inStream <code>true</code> if the input stream is closed;
     *        <code>false</code> if the output stream is closed
     * @throws IOException if an IO error occurs
     *
     * @hide
     */
    public void streamClosed(boolean inStream) throws IOException {

    }

    /** @hide */
    public void noBodyHeader(){
        mSendBodyHeader = false;
    }

    /**
     * Returns whether the operation is aborted.
     */
    public boolean isAborted() {
        return mAborted;
    }

    /**
     * Set whether the operation is aborted.
     *
     * @param aborted {@code true} if the operation is aborted, {@code false} otherwise
     */
    public void setAborted(boolean aborted) {
        this.mAborted = aborted;
    }
}
