19439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly/*
29439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * Copyright (c) 2008-2009, Motorola, Inc.
39439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly *
49439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * All rights reserved.
59439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly *
69439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * Redistribution and use in source and binary forms, with or without
79439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * modification, are permitted provided that the following conditions are met:
89439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly *
99439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * - Redistributions of source code must retain the above copyright notice,
109439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * this list of conditions and the following disclaimer.
119439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly *
129439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * - Redistributions in binary form must reproduce the above copyright notice,
139439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * this list of conditions and the following disclaimer in the documentation
149439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * and/or other materials provided with the distribution.
159439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly *
169439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * - Neither the name of the Motorola, Inc. nor the names of its contributors
179439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * may be used to endorse or promote products derived from this software
189439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * without specific prior written permission.
199439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly *
209439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
219439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
229439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
239439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
249439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
259439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
269439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
279439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
289439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
299439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
309439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * POSSIBILITY OF SUCH DAMAGE.
319439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly */
329439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
339439a7fe517b858bc5e5c654b459315e4722feb2Nick Pellypackage javax.obex;
349439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
359439a7fe517b858bc5e5c654b459315e4722feb2Nick Pellyimport java.io.IOException;
369439a7fe517b858bc5e5c654b459315e4722feb2Nick Pellyimport java.io.InputStream;
379439a7fe517b858bc5e5c654b459315e4722feb2Nick Pellyimport java.io.DataInputStream;
389439a7fe517b858bc5e5c654b459315e4722feb2Nick Pellyimport java.io.OutputStream;
399439a7fe517b858bc5e5c654b459315e4722feb2Nick Pellyimport java.io.DataOutputStream;
409439a7fe517b858bc5e5c654b459315e4722feb2Nick Pellyimport java.io.ByteArrayOutputStream;
419439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
429439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly/**
439439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * This class implements the Operation interface for server side connections.
449439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * <P>
4505ff98bbefda39b9ff26f8bca132cfd0248745c6Tao Liejun * <STRONG>Request Codes</STRONG> There are four different request codes that
4605ff98bbefda39b9ff26f8bca132cfd0248745c6Tao Liejun * are in this class. 0x02 is a PUT request that signals that the request is not
4705ff98bbefda39b9ff26f8bca132cfd0248745c6Tao Liejun * complete and requires an additional OBEX packet. 0x82 is a PUT request that
4805ff98bbefda39b9ff26f8bca132cfd0248745c6Tao Liejun * says that request is complete. In this case, the server can begin sending the
4905ff98bbefda39b9ff26f8bca132cfd0248745c6Tao Liejun * response. The 0x03 is a GET request that signals that the request is not
5005ff98bbefda39b9ff26f8bca132cfd0248745c6Tao Liejun * finished. When the server receives a 0x83, the client is signaling the server
5105ff98bbefda39b9ff26f8bca132cfd0248745c6Tao Liejun * that it is done with its request. TODO: Extend the ClientOperation and reuse
5205ff98bbefda39b9ff26f8bca132cfd0248745c6Tao Liejun * the methods defined TODO: in that class.
532e0da96e757a977154063f980d3f4e1abd41cf09Nick Pelly * @hide
549439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly */
553998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejunpublic final class ServerOperation implements Operation, BaseStream {
569439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
573998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun    public boolean isAborted;
589439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
593998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun    public HeaderSet requestHeader;
609439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
613998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun    public HeaderSet replyHeader;
629439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
633998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun    public boolean finalBitSet;
649439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
653998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun    private InputStream mInput;
669439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
673998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun    private ServerSession mParent;
689439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
693998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun    private int mMaxPacketLength;
702e0da96e757a977154063f980d3f4e1abd41cf09Nick Pelly
713998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun    private int mResponseSize;
729439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
733998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun    private boolean mClosed;
749439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
753998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun    private boolean mGetOperation;
769439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
773998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun    private PrivateInputStream mPrivateInput;
789439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
793998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun    private PrivateOutputStream mPrivateOutput;
809439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
813998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun    private boolean mPrivateOutputOpen;
829439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
833998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun    private String mExceptionString;
849439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
853998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun    private ServerRequestHandler mListener;
869439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
873998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun    private boolean mRequestFinished;
889439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
893998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun    private boolean mHasBody;
909439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
91fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie    private boolean mSendBodyHeader = true;
92fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie
939439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    /**
943998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun     * Creates new ServerOperation
959439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     * @param p the parent that created this object
969439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     * @param in the input stream to read from
979439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     * @param out the output stream to write to
989439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     * @param request the initial request that was received from the client
999439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     * @param maxSize the max packet size that the client will accept
1009439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     * @param listen the listener that is responding to the request
1012e0da96e757a977154063f980d3f4e1abd41cf09Nick Pelly     * @throws IOException if an IO error occurs
1029439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     */
1039439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    public ServerOperation(ServerSession p, InputStream in, int request, int maxSize,
1049439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            ServerRequestHandler listen) throws IOException {
1059439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
1069439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        isAborted = false;
1073998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun        mParent = p;
1083998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun        mInput = in;
1093998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun        mMaxPacketLength = maxSize;
1103998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun        mClosed = false;
1113998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun        requestHeader = new HeaderSet();
1123998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun        replyHeader = new HeaderSet();
1133998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun        mPrivateInput = new PrivateInputStream(this);
1143998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun        mResponseSize = 3;
1153998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun        mListener = listen;
1163998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun        mRequestFinished = false;
1173998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun        mPrivateOutputOpen = false;
1183998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun        mHasBody = false;
1199439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        int bytesReceived;
1209439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
1219439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        /*
1229439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly         * Determine if this is a PUT request
1239439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly         */
1249439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        if ((request == 0x02) || (request == 0x82)) {
1259439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            /*
1269439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly             * It is a PUT request.
1279439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly             */
1283998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun            mGetOperation = false;
12965208317ba9d16486b47ebcaa868c596d424c87fLixin Yue
13065208317ba9d16486b47ebcaa868c596d424c87fLixin Yue            /*
13165208317ba9d16486b47ebcaa868c596d424c87fLixin Yue             * Determine if the final bit is set
13265208317ba9d16486b47ebcaa868c596d424c87fLixin Yue             */
13365208317ba9d16486b47ebcaa868c596d424c87fLixin Yue            if ((request & 0x80) == 0) {
13465208317ba9d16486b47ebcaa868c596d424c87fLixin Yue                finalBitSet = false;
13565208317ba9d16486b47ebcaa868c596d424c87fLixin Yue            } else {
13665208317ba9d16486b47ebcaa868c596d424c87fLixin Yue                finalBitSet = true;
13765208317ba9d16486b47ebcaa868c596d424c87fLixin Yue                mRequestFinished = true;
13865208317ba9d16486b47ebcaa868c596d424c87fLixin Yue            }
13965208317ba9d16486b47ebcaa868c596d424c87fLixin Yue        } else if ((request == 0x03) || (request == 0x83)) {
1409439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            /*
1419439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly             * It is a GET request.
1429439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly             */
1433998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun            mGetOperation = true;
1449439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
14565208317ba9d16486b47ebcaa868c596d424c87fLixin Yue            // For Get request, final bit set is decided by server side logic
1469439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            finalBitSet = false;
14765208317ba9d16486b47ebcaa868c596d424c87fLixin Yue
14865208317ba9d16486b47ebcaa868c596d424c87fLixin Yue            if (request == 0x83) {
14965208317ba9d16486b47ebcaa868c596d424c87fLixin Yue                mRequestFinished = true;
15065208317ba9d16486b47ebcaa868c596d424c87fLixin Yue            }
1519439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        } else {
15265208317ba9d16486b47ebcaa868c596d424c87fLixin Yue            throw new IOException("ServerOperation can not handle such request");
1539439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        }
1549439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
1559439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        int length = in.read();
1569439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        length = (length << 8) + in.read();
1579439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
1589439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        /*
1599439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly         * Determine if the packet length is larger than this device can receive
1609439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly         */
1612e0da96e757a977154063f980d3f4e1abd41cf09Nick Pelly        if (length > ObexHelper.MAX_PACKET_SIZE_INT) {
1623998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun            mParent.sendResponse(ResponseCodes.OBEX_HTTP_REQ_TOO_LARGE, null);
1639439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            throw new IOException("Packet received was too large");
1649439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        }
1659439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
1669439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        /*
1679439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly         * Determine if any headers were sent in the initial request
1689439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly         */
1699439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        if (length > 3) {
1709439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            byte[] data = new byte[length - 3];
1719439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            bytesReceived = in.read(data);
1729439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
1739439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            while (bytesReceived != data.length) {
1749439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                bytesReceived += in.read(data, bytesReceived, data.length - bytesReceived);
1759439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            }
1769439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
1773998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun            byte[] body = ObexHelper.updateHeaderSet(requestHeader, data);
1789439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
1799439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            if (body != null) {
1803998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun                mHasBody = true;
1819439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            }
1829439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
183e80534ff59b2e62a0ddf4359147b81f5ba10de86Tao Liejun            if (mListener.getConnectionId() != -1 && requestHeader.mConnectionID != null) {
1843998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun                mListener.setConnectionId(ObexHelper.convertToLong(requestHeader.mConnectionID));
1859439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            } else {
186e80534ff59b2e62a0ddf4359147b81f5ba10de86Tao Liejun                mListener.setConnectionId(1);
1879439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            }
1889439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
1893998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun            if (requestHeader.mAuthResp != null) {
1903998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun                if (!mParent.handleAuthResp(requestHeader.mAuthResp)) {
1913998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun                    mExceptionString = "Authentication Failed";
1923998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun                    mParent.sendResponse(ResponseCodes.OBEX_HTTP_UNAUTHORIZED, null);
1933998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun                    mClosed = true;
1943998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun                    requestHeader.mAuthResp = null;
1959439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                    return;
1969439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                }
1979439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            }
1989439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
1993998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun            if (requestHeader.mAuthChall != null) {
2003998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun                mParent.handleAuthChall(requestHeader);
2019439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                // send the  authResp to the client
2023998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun                replyHeader.mAuthResp = new byte[requestHeader.mAuthResp.length];
2033998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun                System.arraycopy(requestHeader.mAuthResp, 0, replyHeader.mAuthResp, 0,
2043998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun                        replyHeader.mAuthResp.length);
2053998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun                requestHeader.mAuthResp = null;
2063998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun                requestHeader.mAuthChall = null;
2079439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
2089439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            }
2099439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
2109439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            if (body != null) {
2113998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun                mPrivateInput.writeBytes(body, 1);
2129439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            } else {
2133998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun                while ((!mGetOperation) && (!finalBitSet)) {
2143998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun                    sendReply(ResponseCodes.OBEX_HTTP_CONTINUE);
2153998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun                    if (mPrivateInput.available() > 0) {
2169439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                        break;
2179439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                    }
2189439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                }
2193998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun            }
2203998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun        }
2219439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
2223998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun        while ((!mGetOperation) && (!finalBitSet) && (mPrivateInput.available() == 0)) {
2233998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun            sendReply(ResponseCodes.OBEX_HTTP_CONTINUE);
2243998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun            if (mPrivateInput.available() > 0) {
2259439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                break;
2269439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            }
2279439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        }
2289439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
2299439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        // wait for get request finished !!!!
23065208317ba9d16486b47ebcaa868c596d424c87fLixin Yue        while (mGetOperation && !mRequestFinished) {
2313998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun            sendReply(ResponseCodes.OBEX_HTTP_CONTINUE);
2329439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        }
2339439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    }
2349439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
2353998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun    public boolean isValidBody() {
2363998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun        return mHasBody;
2379439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    }
2389439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
2399439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    /**
24005ff98bbefda39b9ff26f8bca132cfd0248745c6Tao Liejun     * Determines if the operation should continue or should wait. If it should
24105ff98bbefda39b9ff26f8bca132cfd0248745c6Tao Liejun     * continue, this method will continue the operation.
2429439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     * @param sendEmpty if <code>true</code> then this will continue the
24305ff98bbefda39b9ff26f8bca132cfd0248745c6Tao Liejun     *        operation even if no headers will be sent; if <code>false</code>
24405ff98bbefda39b9ff26f8bca132cfd0248745c6Tao Liejun     *        then this method will only continue the operation if there are
24505ff98bbefda39b9ff26f8bca132cfd0248745c6Tao Liejun     *        headers to send
24605ff98bbefda39b9ff26f8bca132cfd0248745c6Tao Liejun     * @param inStream if<code>true</code> the stream is input stream, otherwise
24705ff98bbefda39b9ff26f8bca132cfd0248745c6Tao Liejun     *        output stream
2489439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     * @return <code>true</code> if the operation was completed;
24905ff98bbefda39b9ff26f8bca132cfd0248745c6Tao Liejun     *         <code>false</code> if no operation took place
2509439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     */
2519439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    public synchronized boolean continueOperation(boolean sendEmpty, boolean inStream)
2529439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            throws IOException {
2533998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun        if (!mGetOperation) {
2549439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            if (!finalBitSet) {
2559439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                if (sendEmpty) {
2563998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun                    sendReply(ResponseCodes.OBEX_HTTP_CONTINUE);
2579439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                    return true;
2589439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                } else {
2593998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun                    if ((mResponseSize > 3) || (mPrivateOutput.size() > 0)) {
2603998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun                        sendReply(ResponseCodes.OBEX_HTTP_CONTINUE);
2619439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                        return true;
2629439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                    } else {
2639439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                        return false;
2649439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                    }
2659439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                }
2669439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            } else {
2679439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                return false;
2689439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            }
2699439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        } else {
2703998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun            sendReply(ResponseCodes.OBEX_HTTP_CONTINUE);
2719439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            return true;
2729439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        }
2739439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    }
2749439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
2759439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    /**
27605ff98bbefda39b9ff26f8bca132cfd0248745c6Tao Liejun     * Sends a reply to the client. If the reply is a OBEX_HTTP_CONTINUE, it
2779439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     * will wait for a response from the client before ending.
2789439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     * @param type the response code to send back to the client
2799439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     * @return <code>true</code> if the final bit was not set on the reply;
28005ff98bbefda39b9ff26f8bca132cfd0248745c6Tao Liejun     *         <code>false</code> if no reply was received because the operation
28105ff98bbefda39b9ff26f8bca132cfd0248745c6Tao Liejun     *         ended, an abort was received, or the final bit was set in the
28205ff98bbefda39b9ff26f8bca132cfd0248745c6Tao Liejun     *         reply
2832e0da96e757a977154063f980d3f4e1abd41cf09Nick Pelly     * @throws IOException if an IO error occurs
2849439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     */
2853998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun    public synchronized boolean sendReply(int type) throws IOException {
2869439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        ByteArrayOutputStream out = new ByteArrayOutputStream();
2879439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        int bytesReceived;
2889439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
2893998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun        long id = mListener.getConnectionId();
2909439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        if (id == -1) {
2913998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun            replyHeader.mConnectionID = null;
2929439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        } else {
2933998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun            replyHeader.mConnectionID = ObexHelper.convertToByteArray(id);
2949439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        }
2959439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
2963998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun        byte[] headerArray = ObexHelper.createHeader(replyHeader, true);
2979439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        int bodyLength = -1;
2989439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        int orginalBodyLength = -1;
2999439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
3003998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun        if (mPrivateOutput != null) {
3013998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun            bodyLength = mPrivateOutput.size();
3029439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            orginalBodyLength = bodyLength;
3039439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        }
3049439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
3053998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun        if ((ObexHelper.BASE_PACKET_LENGTH + headerArray.length) > mMaxPacketLength) {
3069439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
3079439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            int end = 0;
3089439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            int start = 0;
3099439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
3109439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            while (end != headerArray.length) {
3113998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun                end = ObexHelper.findHeaderEnd(headerArray, start, mMaxPacketLength
3123998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun                        - ObexHelper.BASE_PACKET_LENGTH);
3139439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                if (end == -1) {
3149439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
3153998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun                    mClosed = true;
3169439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
3173998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun                    if (mPrivateInput != null) {
3183998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun                        mPrivateInput.close();
3199439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                    }
3209439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
3213998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun                    if (mPrivateOutput != null) {
3223998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun                        mPrivateOutput.close();
3239439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                    }
3243998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun                    mParent.sendResponse(ResponseCodes.OBEX_HTTP_INTERNAL_ERROR, null);
3259439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                    throw new IOException("OBEX Packet exceeds max packet size");
3269439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                }
3279439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                byte[] sendHeader = new byte[end - start];
3289439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                System.arraycopy(headerArray, start, sendHeader, 0, sendHeader.length);
3299439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
3303998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun                mParent.sendResponse(type, sendHeader);
3319439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                start = end;
3329439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            }
3339439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
3349439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            if (bodyLength > 0) {
3359439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                return true;
3369439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            } else {
3379439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                return false;
3389439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            }
3399439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
3409439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        } else {
3419439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            out.write(headerArray);
3429439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        }
3439439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
34465208317ba9d16486b47ebcaa868c596d424c87fLixin Yue        // For Get operation: if response code is OBEX_HTTP_OK, then this is the
34565208317ba9d16486b47ebcaa868c596d424c87fLixin Yue        // last packet; so set finalBitSet to true.
34665208317ba9d16486b47ebcaa868c596d424c87fLixin Yue        if (mGetOperation && type == ResponseCodes.OBEX_HTTP_OK) {
34765208317ba9d16486b47ebcaa868c596d424c87fLixin Yue            finalBitSet = true;
34865208317ba9d16486b47ebcaa868c596d424c87fLixin Yue        }
34965208317ba9d16486b47ebcaa868c596d424c87fLixin Yue
3503998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun        if ((finalBitSet) || (headerArray.length < (mMaxPacketLength - 20))) {
3519439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            if (bodyLength > 0) {
3529439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                /*
3539439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                 * Determine if I can send the whole body or just part of
3549439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                 * the body.  Remember that there is the 3 bytes for the
3559439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                 * response message and 3 bytes for the header ID and length
3569439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                 */
3573998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun                if (bodyLength > (mMaxPacketLength - headerArray.length - 6)) {
3583998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun                    bodyLength = mMaxPacketLength - headerArray.length - 6;
3599439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                }
3609439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
3613998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun                byte[] body = mPrivateOutput.readBytes(bodyLength);
3629439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
3639439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                /*
3649439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                 * Since this is a put request if the final bit is set or
3659439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                 * the output stream is closed we need to send the 0x49
3669439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                 * (End of Body) otherwise, we need to send 0x48 (Body)
3679439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                 */
3683998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun                if ((finalBitSet) || (mPrivateOutput.isClosed())) {
369fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie                    if(mSendBodyHeader == true) {
370fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie                        out.write(0x49);
371fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie                        bodyLength += 3;
372fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie                        out.write((byte)(bodyLength >> 8));
373fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie                        out.write((byte)bodyLength);
374fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie                        out.write(body);
375fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie                    }
3769439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                } else {
377fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie                    if(mSendBodyHeader == true) {
3789439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                    out.write(0x48);
379fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie                    bodyLength += 3;
380fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie                    out.write((byte)(bodyLength >> 8));
381fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie                    out.write((byte)bodyLength);
382fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie                    out.write(body);
383fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie                    }
3849439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                }
3859439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
3869439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            }
3879439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        }
3889439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
3899439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        if ((finalBitSet) && (type == ResponseCodes.OBEX_HTTP_OK) && (orginalBodyLength <= 0)) {
390fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie            if(mSendBodyHeader == true) {
391fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie                out.write(0x49);
392fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie                orginalBodyLength = 3;
393fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie                out.write((byte)(orginalBodyLength >> 8));
394fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie                out.write((byte)orginalBodyLength);
395fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie            }
3969439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        }
3979439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
3983998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun        mResponseSize = 3;
3993998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun        mParent.sendResponse(type, out.toByteArray());
4009439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
4013998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun        if (type == ResponseCodes.OBEX_HTTP_CONTINUE) {
4023998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun            int headerID = mInput.read();
4033998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun            int length = mInput.read();
4043998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun            length = (length << 8) + mInput.read();
4053998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun            if ((headerID != ObexHelper.OBEX_OPCODE_PUT)
4063998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun                    && (headerID != ObexHelper.OBEX_OPCODE_PUT_FINAL)
4073998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun                    && (headerID != ObexHelper.OBEX_OPCODE_GET)
4083998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun                    && (headerID != ObexHelper.OBEX_OPCODE_GET_FINAL)) {
4099439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
4109439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                if (length > 3) {
4114507b177c35cfd918dba1cdc325fae3688fb7bd2Anders Petersson                    byte[] temp = new byte[length - 3];
4124507b177c35cfd918dba1cdc325fae3688fb7bd2Anders Petersson                    // First three bytes already read, compensating for this
4133998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun                    bytesReceived = mInput.read(temp);
4149439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
4154507b177c35cfd918dba1cdc325fae3688fb7bd2Anders Petersson                    while (bytesReceived != temp.length) {
4164507b177c35cfd918dba1cdc325fae3688fb7bd2Anders Petersson                        bytesReceived += mInput.read(temp, bytesReceived,
4174507b177c35cfd918dba1cdc325fae3688fb7bd2Anders Petersson                                temp.length - bytesReceived);
4189439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                    }
4199439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                }
4209439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
4219439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                /*
4229439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                 * Determine if an ABORT was sent as the reply
4239439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                 */
4243998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun                if (headerID == ObexHelper.OBEX_OPCODE_ABORT) {
4253998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun                    mParent.sendResponse(ResponseCodes.OBEX_HTTP_OK, null);
4263998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun                    mClosed = true;
4279439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                    isAborted = true;
4283998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun                    mExceptionString = "Abort Received";
4299439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                    throw new IOException("Abort Received");
4309439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                } else {
4313998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun                    mParent.sendResponse(ResponseCodes.OBEX_HTTP_BAD_REQUEST, null);
4323998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun                    mClosed = true;
4333998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun                    mExceptionString = "Bad Request Received";
4349439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                    throw new IOException("Bad Request Received");
4359439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                }
4369439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            } else {
4379439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
43865208317ba9d16486b47ebcaa868c596d424c87fLixin Yue                if ((headerID == ObexHelper.OBEX_OPCODE_PUT_FINAL)) {
4399439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                    finalBitSet = true;
44065208317ba9d16486b47ebcaa868c596d424c87fLixin Yue                } else if (headerID == ObexHelper.OBEX_OPCODE_GET_FINAL) {
44165208317ba9d16486b47ebcaa868c596d424c87fLixin Yue                    mRequestFinished = true;
4429439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                }
4439439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
4449439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                /*
4459439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                 * Determine if the packet length is larger then this device can receive
4469439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                 */
4472e0da96e757a977154063f980d3f4e1abd41cf09Nick Pelly                if (length > ObexHelper.MAX_PACKET_SIZE_INT) {
4483998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun                    mParent.sendResponse(ResponseCodes.OBEX_HTTP_REQ_TOO_LARGE, null);
4499439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                    throw new IOException("Packet received was too large");
4509439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                }
4519439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
4529439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                /*
4539439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                 * Determine if any headers were sent in the initial request
4549439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                 */
4559439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                if (length > 3) {
4569439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                    byte[] data = new byte[length - 3];
4573998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun                    bytesReceived = mInput.read(data);
4589439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
4599439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                    while (bytesReceived != data.length) {
4603998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun                        bytesReceived += mInput.read(data, bytesReceived, data.length
4619439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                                - bytesReceived);
4629439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                    }
4633998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun                    byte[] body = ObexHelper.updateHeaderSet(requestHeader, data);
4649439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                    if (body != null) {
4653998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun                        mHasBody = true;
4669439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                    }
467e80534ff59b2e62a0ddf4359147b81f5ba10de86Tao Liejun                    if (mListener.getConnectionId() != -1 && requestHeader.mConnectionID != null) {
4683998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun                        mListener.setConnectionId(ObexHelper
4693998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun                                .convertToLong(requestHeader.mConnectionID));
4709439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                    } else {
4713998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun                        mListener.setConnectionId(1);
4729439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                    }
4739439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
4743998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun                    if (requestHeader.mAuthResp != null) {
4753998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun                        if (!mParent.handleAuthResp(requestHeader.mAuthResp)) {
4763998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun                            mExceptionString = "Authentication Failed";
4773998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun                            mParent.sendResponse(ResponseCodes.OBEX_HTTP_UNAUTHORIZED, null);
4783998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun                            mClosed = true;
4793998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun                            requestHeader.mAuthResp = null;
4809439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                            return false;
4819439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                        }
4823998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun                        requestHeader.mAuthResp = null;
4839439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                    }
4849439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
4853998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun                    if (requestHeader.mAuthChall != null) {
4863998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun                        mParent.handleAuthChall(requestHeader);
4879439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                        // send the auhtResp to the client
4883998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun                        replyHeader.mAuthResp = new byte[requestHeader.mAuthResp.length];
4893998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun                        System.arraycopy(requestHeader.mAuthResp, 0, replyHeader.mAuthResp, 0,
4903998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun                                replyHeader.mAuthResp.length);
4913998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun                        requestHeader.mAuthResp = null;
4923998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun                        requestHeader.mAuthChall = null;
4939439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                    }
4949439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
4959439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                    if (body != null) {
4963998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun                        mPrivateInput.writeBytes(body, 1);
4979439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                    }
4989439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                }
4999439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            }
5009439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            return true;
5019439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        } else {
5029439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            return false;
5039439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        }
5049439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    }
5059439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
5069439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    /**
50705ff98bbefda39b9ff26f8bca132cfd0248745c6Tao Liejun     * Sends an ABORT message to the server. By calling this method, the
5089439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     * corresponding input and output streams will be closed along with this
5099439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     * object.
51005ff98bbefda39b9ff26f8bca132cfd0248745c6Tao Liejun     * @throws IOException if the transaction has already ended or if an OBEX
51105ff98bbefda39b9ff26f8bca132cfd0248745c6Tao Liejun     *         server called this method
5129439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     */
5139439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    public void abort() throws IOException {
5149439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        throw new IOException("Called from a server");
5159439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    }
5169439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
5179439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    /**
5189439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     * Returns the headers that have been received during the operation.
51905ff98bbefda39b9ff26f8bca132cfd0248745c6Tao Liejun     * Modifying the object returned has no effect on the headers that are sent
52005ff98bbefda39b9ff26f8bca132cfd0248745c6Tao Liejun     * or retrieved.
5219439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     * @return the headers received during this <code>Operation</code>
5222e0da96e757a977154063f980d3f4e1abd41cf09Nick Pelly     * @throws IOException if this <code>Operation</code> has been closed
5239439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     */
5243998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun    public HeaderSet getReceivedHeader() throws IOException {
5259439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        ensureOpen();
5263998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun        return requestHeader;
5279439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    }
5289439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
5299439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    /**
5309439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     * Specifies the headers that should be sent in the next OBEX message that
5319439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     * is sent.
5329439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     * @param headers the headers to send in the next message
53305ff98bbefda39b9ff26f8bca132cfd0248745c6Tao Liejun     * @throws IOException if this <code>Operation</code> has been closed or the
53405ff98bbefda39b9ff26f8bca132cfd0248745c6Tao Liejun     *         transaction has ended and no further messages will be exchanged
5352e0da96e757a977154063f980d3f4e1abd41cf09Nick Pelly     * @throws IllegalArgumentException if <code>headers</code> was not created
53605ff98bbefda39b9ff26f8bca132cfd0248745c6Tao Liejun     *         by a call to <code>ServerRequestHandler.createHeaderSet()</code>
5379439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     */
5389439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    public void sendHeaders(HeaderSet headers) throws IOException {
5399439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        ensureOpen();
5409439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
5419439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        if (headers == null) {
5423998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun            throw new IOException("Headers may not be null");
5439439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        }
5449439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
5459439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        int[] headerList = headers.getHeaderList();
5469439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        if (headerList != null) {
5479439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            for (int i = 0; i < headerList.length; i++) {
5483998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun                replyHeader.setHeader(headerList[i], headers.getHeader(headerList[i]));
5499439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            }
5509439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
5519439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        }
5529439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    }
5539439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
5549439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    /**
55505ff98bbefda39b9ff26f8bca132cfd0248745c6Tao Liejun     * Retrieves the response code retrieved from the server. Response codes are
55605ff98bbefda39b9ff26f8bca132cfd0248745c6Tao Liejun     * defined in the <code>ResponseCodes</code> interface.
5579439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     * @return the response code retrieved from the server
5582e0da96e757a977154063f980d3f4e1abd41cf09Nick Pelly     * @throws IOException if an error occurred in the transport layer during
55905ff98bbefda39b9ff26f8bca132cfd0248745c6Tao Liejun     *         the transaction; if this method is called on a
56005ff98bbefda39b9ff26f8bca132cfd0248745c6Tao Liejun     *         <code>HeaderSet</code> object created by calling
56105ff98bbefda39b9ff26f8bca132cfd0248745c6Tao Liejun     *         <code>createHeaderSet</code> in a <code>ClientSession</code>
56205ff98bbefda39b9ff26f8bca132cfd0248745c6Tao Liejun     *         object; if this is called from a server
5639439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     */
5649439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    public int getResponseCode() throws IOException {
5659439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        throw new IOException("Called from a server");
5669439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    }
5679439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
5689439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    /**
5699439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     * Always returns <code>null</code>
5709439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     * @return <code>null</code>
5719439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     */
5729439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    public String getEncoding() {
5739439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        return null;
5749439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    }
5759439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
5769439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    /**
5779439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     * Returns the type of content that the resource connected to is providing.
5789439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     * E.g. if the connection is via HTTP, then the value of the content-type
5799439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     * header field is returned.
5809439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     * @return the content type of the resource that the URL references, or
58105ff98bbefda39b9ff26f8bca132cfd0248745c6Tao Liejun     *         <code>null</code> if not known
5829439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     */
5839439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    public String getType() {
5849439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        try {
5853998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun            return (String)requestHeader.getHeader(HeaderSet.TYPE);
5869439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        } catch (IOException e) {
5879439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            return null;
5889439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        }
5899439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    }
5909439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
5919439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    /**
5929439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     * Returns the length of the content which is being provided. E.g. if the
59305ff98bbefda39b9ff26f8bca132cfd0248745c6Tao Liejun     * connection is via HTTP, then the value of the content-length header field
59405ff98bbefda39b9ff26f8bca132cfd0248745c6Tao Liejun     * is returned.
5959439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     * @return the content length of the resource that this connection's URL
59605ff98bbefda39b9ff26f8bca132cfd0248745c6Tao Liejun     *         references, or -1 if the content length is not known
5979439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     */
5989439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    public long getLength() {
5999439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        try {
6003998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun            Long temp = (Long)requestHeader.getHeader(HeaderSet.LENGTH);
6019439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
6029439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            if (temp == null) {
6039439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                return -1;
6049439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            } else {
6059439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                return temp.longValue();
6069439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            }
6079439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        } catch (IOException e) {
6089439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            return -1;
6099439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        }
6109439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    }
6119439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
6129439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    public int getMaxPacketSize() {
61365208317ba9d16486b47ebcaa868c596d424c87fLixin Yue        return mMaxPacketLength - 6 - getHeaderLength();
61465208317ba9d16486b47ebcaa868c596d424c87fLixin Yue    }
61565208317ba9d16486b47ebcaa868c596d424c87fLixin Yue
61665208317ba9d16486b47ebcaa868c596d424c87fLixin Yue    public int getHeaderLength() {
61765208317ba9d16486b47ebcaa868c596d424c87fLixin Yue        long id = mListener.getConnectionId();
61865208317ba9d16486b47ebcaa868c596d424c87fLixin Yue        if (id == -1) {
61965208317ba9d16486b47ebcaa868c596d424c87fLixin Yue            replyHeader.mConnectionID = null;
62065208317ba9d16486b47ebcaa868c596d424c87fLixin Yue        } else {
62165208317ba9d16486b47ebcaa868c596d424c87fLixin Yue            replyHeader.mConnectionID = ObexHelper.convertToByteArray(id);
62265208317ba9d16486b47ebcaa868c596d424c87fLixin Yue        }
62365208317ba9d16486b47ebcaa868c596d424c87fLixin Yue
62465208317ba9d16486b47ebcaa868c596d424c87fLixin Yue        byte[] headerArray = ObexHelper.createHeader(replyHeader, false);
62565208317ba9d16486b47ebcaa868c596d424c87fLixin Yue
62665208317ba9d16486b47ebcaa868c596d424c87fLixin Yue        return headerArray.length;
6279439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    }
6289439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
6299439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    /**
6309439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     * Open and return an input stream for a connection.
6319439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     * @return an input stream
6322e0da96e757a977154063f980d3f4e1abd41cf09Nick Pelly     * @throws IOException if an I/O error occurs
6339439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     */
6349439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    public InputStream openInputStream() throws IOException {
6359439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        ensureOpen();
6363998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun        return mPrivateInput;
6379439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    }
6389439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
6399439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    /**
6409439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     * Open and return a data input stream for a connection.
6419439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     * @return an input stream
6422e0da96e757a977154063f980d3f4e1abd41cf09Nick Pelly     * @throws IOException if an I/O error occurs
6439439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     */
6449439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    public DataInputStream openDataInputStream() throws IOException {
6459439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        return new DataInputStream(openInputStream());
6469439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    }
6479439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
6489439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    /**
6499439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     * Open and return an output stream for a connection.
6509439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     * @return an output stream
6512e0da96e757a977154063f980d3f4e1abd41cf09Nick Pelly     * @throws IOException if an I/O error occurs
6529439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     */
6539439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    public OutputStream openOutputStream() throws IOException {
6549439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        ensureOpen();
6559439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
6563998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun        if (mPrivateOutputOpen) {
6579439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            throw new IOException("no more input streams available, stream already opened");
6583998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun        }
6599439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
6603998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun        if (!mRequestFinished) {
6619439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            throw new IOException("no  output streams available ,request not finished");
6623998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun        }
6639439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
6643998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun        if (mPrivateOutput == null) {
66565208317ba9d16486b47ebcaa868c596d424c87fLixin Yue            mPrivateOutput = new PrivateOutputStream(this, getMaxPacketSize());
6669439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        }
6673998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun        mPrivateOutputOpen = true;
6683998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun        return mPrivateOutput;
6699439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    }
6709439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
6719439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    /**
6729439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     * Open and return a data output stream for a connection.
6739439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     * @return an output stream
6742e0da96e757a977154063f980d3f4e1abd41cf09Nick Pelly     * @throws IOException if an I/O error occurs
6759439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     */
6769439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    public DataOutputStream openDataOutputStream() throws IOException {
6779439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        return new DataOutputStream(openOutputStream());
6789439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    }
6799439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
6809439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    /**
6819439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     * Closes the connection and ends the transaction
6822e0da96e757a977154063f980d3f4e1abd41cf09Nick Pelly     * @throws IOException if the operation has already ended or is closed
6839439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     */
6849439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    public void close() throws IOException {
6859439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        ensureOpen();
6863998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun        mClosed = true;
6879439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    }
6889439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
6899439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    /**
6909439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     * Verifies that the connection is open and no exceptions should be thrown.
6912e0da96e757a977154063f980d3f4e1abd41cf09Nick Pelly     * @throws IOException if an exception needs to be thrown
6929439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     */
6939439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    public void ensureOpen() throws IOException {
6943998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun        if (mExceptionString != null) {
6953998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun            throw new IOException(mExceptionString);
6969439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        }
6973998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun        if (mClosed) {
6989439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            throw new IOException("Operation has already ended");
6999439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        }
7009439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    }
7019439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
7029439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    /**
70305ff98bbefda39b9ff26f8bca132cfd0248745c6Tao Liejun     * Verifies that additional information may be sent. In other words, the
7049439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     * operation is not done.
7059439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     * <P>
70605ff98bbefda39b9ff26f8bca132cfd0248745c6Tao Liejun     * Included to implement the BaseStream interface only. It does not do
7079439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     * anything on the server side since the operation of the Operation object
7089439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     * is not done until after the handler returns from its method.
7092e0da96e757a977154063f980d3f4e1abd41cf09Nick Pelly     * @throws IOException if the operation is completed
7109439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     */
7119439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    public void ensureNotDone() throws IOException {
7129439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    }
7139439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
7149439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    /**
71505ff98bbefda39b9ff26f8bca132cfd0248745c6Tao Liejun     * Called when the output or input stream is closed. It does not do anything
71605ff98bbefda39b9ff26f8bca132cfd0248745c6Tao Liejun     * on the server side since the operation of the Operation object is not
71705ff98bbefda39b9ff26f8bca132cfd0248745c6Tao Liejun     * done until after the handler returns from its method.
7189439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     * @param inStream <code>true</code> if the input stream is closed;
71905ff98bbefda39b9ff26f8bca132cfd0248745c6Tao Liejun     *        <code>false</code> if the output stream is closed
7202e0da96e757a977154063f980d3f4e1abd41cf09Nick Pelly     * @throws IOException if an IO error occurs
7219439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     */
7229439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    public void streamClosed(boolean inStream) throws IOException {
7239439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
7249439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    }
725fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie
726fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie    public void noBodyHeader(){
727fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie        mSendBodyHeader = false;
728fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie    }
7299439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly}
730