19439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly/*
2238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde * Copyright (c) 2015 The Android Open Source Project
3238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde * Copyright (C) 2015 Samsung LSI
49439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * Copyright (c) 2008-2009, Motorola, Inc.
59439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly *
69439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * All rights reserved.
79439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly *
89439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * Redistribution and use in source and binary forms, with or without
99439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * modification, are permitted provided that the following conditions are met:
109439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly *
119439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * - Redistributions of source code must retain the above copyright notice,
129439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * this list of conditions and the following disclaimer.
139439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly *
149439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * - Redistributions in binary form must reproduce the above copyright notice,
159439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * this list of conditions and the following disclaimer in the documentation
169439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * and/or other materials provided with the distribution.
179439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly *
189439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * - Neither the name of the Motorola, Inc. nor the names of its contributors
199439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * may be used to endorse or promote products derived from this software
209439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * without specific prior written permission.
219439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly *
229439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
239439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
249439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
259439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
269439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
279439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
289439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
299439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
309439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
319439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
329439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * POSSIBILITY OF SUCH DAMAGE.
339439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly */
349439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
359439a7fe517b858bc5e5c654b459315e4722feb2Nick Pellypackage javax.obex;
369439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
379439a7fe517b858bc5e5c654b459315e4722feb2Nick Pellyimport java.io.IOException;
389439a7fe517b858bc5e5c654b459315e4722feb2Nick Pellyimport java.io.InputStream;
399439a7fe517b858bc5e5c654b459315e4722feb2Nick Pellyimport java.io.OutputStream;
409439a7fe517b858bc5e5c654b459315e4722feb2Nick Pellyimport java.io.DataInputStream;
419439a7fe517b858bc5e5c654b459315e4722feb2Nick Pellyimport java.io.DataOutputStream;
429439a7fe517b858bc5e5c654b459315e4722feb2Nick Pellyimport java.io.ByteArrayOutputStream;
439439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
44238e0f934f1f47263b384bc745ae0678c777130dCasper Bondeimport android.util.Log;
45238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde
469439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly/**
4705ff98bbefda39b9ff26f8bca132cfd0248745c6Tao Liejun * This class implements the <code>Operation</code> interface. It will read and
4805ff98bbefda39b9ff26f8bca132cfd0248745c6Tao Liejun * write data via puts and gets.
492e0da96e757a977154063f980d3f4e1abd41cf09Nick Pelly * @hide
509439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly */
512e0da96e757a977154063f980d3f4e1abd41cf09Nick Pellypublic final class ClientOperation implements Operation, BaseStream {
529439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
53238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde    private static final String TAG = "ClientOperation";
54238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde
55238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde    private static final boolean V = ObexHelper.VDBG;
56238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde
573998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun    private ClientSession mParent;
589439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
593998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun    private boolean mInputOpen;
609439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
613998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun    private PrivateInputStream mPrivateInput;
629439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
633998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun    private boolean mPrivateInputOpen;
649439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
653998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun    private PrivateOutputStream mPrivateOutput;
669439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
673998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun    private boolean mPrivateOutputOpen;
689439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
693998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun    private String mExceptionMessage;
709439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
713998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun    private int mMaxPacketSize;
729439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
733998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun    private boolean mOperationDone;
749439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
753998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun    private boolean mGetOperation;
769439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
778949bfb90c415629dbd0e30d25003fb3e0375fb5Hemant Gupta    private boolean mGetFinalFlag;
788949bfb90c415629dbd0e30d25003fb3e0375fb5Hemant Gupta
793998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun    private HeaderSet mRequestHeader;
809439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
813998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun    private HeaderSet mReplyHeader;
829439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
833998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun    private boolean mEndOfBodySent;
849439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
85238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde    private boolean mSendBodyHeader = true;
86238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde    // A latch - when triggered, there is not way back ;-)
87238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde    private boolean mSrmActive = false;
88238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde
89238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde    // Assume SRM disabled - until support is confirmed
90238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde    // by the server
91238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde    private boolean mSrmEnabled = false;
92238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde    // keep waiting until final-bit is received in request
93238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde    // to handle the case where the SRM enable header is in
94238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde    // a different OBEX packet than the SRMP header.
95238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde    private boolean mSrmWaitingForRemote = true;
96238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde
97238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde
9805ff98bbefda39b9ff26f8bca132cfd0248745c6Tao Liejun    /**
999439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     * Creates new OperationImpl to read and write data to a server
1009439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     * @param maxSize the maximum packet size
1019439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     * @param p the parent to this object
1029439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     * @param type <code>true</code> if this is a get request;
10305ff98bbefda39b9ff26f8bca132cfd0248745c6Tao Liejun     *        <code>false</code. if this is a put request
10405ff98bbefda39b9ff26f8bca132cfd0248745c6Tao Liejun     * @param header the header to set in the initial request
10505ff98bbefda39b9ff26f8bca132cfd0248745c6Tao Liejun     * @throws IOException if the an IO error occurred
1069439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     */
1073998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun    public ClientOperation(int maxSize, ClientSession p, HeaderSet header, boolean type)
1083998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun            throws IOException {
1099439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
1103998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun        mParent = p;
1113998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun        mEndOfBodySent = false;
1123998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun        mInputOpen = true;
1133998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun        mOperationDone = false;
1143998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun        mMaxPacketSize = maxSize;
1153998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun        mGetOperation = type;
1168949bfb90c415629dbd0e30d25003fb3e0375fb5Hemant Gupta        mGetFinalFlag = false;
1179439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
1183998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun        mPrivateInputOpen = false;
1193998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun        mPrivateOutputOpen = false;
1203998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun        mPrivateInput = null;
1213998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun        mPrivateOutput = null;
1229439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
1233998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun        mReplyHeader = new HeaderSet();
1249439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
1253998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun        mRequestHeader = new HeaderSet();
1269439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
1279439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        int[] headerList = header.getHeaderList();
1289439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
1299439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        if (headerList != null) {
1309439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
1319439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            for (int i = 0; i < headerList.length; i++) {
1323998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun                mRequestHeader.setHeader(headerList[i], header.getHeader(headerList[i]));
1339439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            }
1349439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        }
1359439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
1363998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun        if ((header).mAuthChall != null) {
1373998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun            mRequestHeader.mAuthChall = new byte[(header).mAuthChall.length];
1383998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun            System.arraycopy((header).mAuthChall, 0, mRequestHeader.mAuthChall, 0,
1393998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun                    (header).mAuthChall.length);
1409439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        }
1419439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
1423998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun        if ((header).mAuthResp != null) {
1433998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun            mRequestHeader.mAuthResp = new byte[(header).mAuthResp.length];
1443998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun            System.arraycopy((header).mAuthResp, 0, mRequestHeader.mAuthResp, 0,
1453998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun                    (header).mAuthResp.length);
1469439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
1479439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        }
1480d376053747615ac7c4b45ab7810329ffbdf80d1Kim Schulz
1490d376053747615ac7c4b45ab7810329ffbdf80d1Kim Schulz        if ((header).mConnectionID != null) {
1500d376053747615ac7c4b45ab7810329ffbdf80d1Kim Schulz            mRequestHeader.mConnectionID = new byte[4];
1510d376053747615ac7c4b45ab7810329ffbdf80d1Kim Schulz            System.arraycopy((header).mConnectionID, 0, mRequestHeader.mConnectionID, 0,
1520d376053747615ac7c4b45ab7810329ffbdf80d1Kim Schulz                    4);
1530d376053747615ac7c4b45ab7810329ffbdf80d1Kim Schulz
1540d376053747615ac7c4b45ab7810329ffbdf80d1Kim Schulz        }
1559439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    }
1569439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
1579439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    /**
1588949bfb90c415629dbd0e30d25003fb3e0375fb5Hemant Gupta     * Allows to set flag which will force GET to be always sent as single packet request with
1598949bfb90c415629dbd0e30d25003fb3e0375fb5Hemant Gupta     * final flag set. This is to improve compatibility with some profiles, i.e. PBAP which
1608949bfb90c415629dbd0e30d25003fb3e0375fb5Hemant Gupta     * require requests to be sent this way.
1618949bfb90c415629dbd0e30d25003fb3e0375fb5Hemant Gupta     */
1628949bfb90c415629dbd0e30d25003fb3e0375fb5Hemant Gupta    public void setGetFinalFlag(boolean flag) {
1638949bfb90c415629dbd0e30d25003fb3e0375fb5Hemant Gupta        mGetFinalFlag = flag;
1648949bfb90c415629dbd0e30d25003fb3e0375fb5Hemant Gupta    }
1658949bfb90c415629dbd0e30d25003fb3e0375fb5Hemant Gupta
1668949bfb90c415629dbd0e30d25003fb3e0375fb5Hemant Gupta    /**
16705ff98bbefda39b9ff26f8bca132cfd0248745c6Tao Liejun     * Sends an ABORT message to the server. By calling this method, the
1689439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     * corresponding input and output streams will be closed along with this
1699439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     * object.
17005ff98bbefda39b9ff26f8bca132cfd0248745c6Tao Liejun     * @throws IOException if the transaction has already ended or if an OBEX
17105ff98bbefda39b9ff26f8bca132cfd0248745c6Tao Liejun     *         server called this method
1729439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     */
1739439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    public synchronized void abort() throws IOException {
1749439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        ensureOpen();
1759439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        //no compatible with sun-ri
1763998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun        if ((mOperationDone) && (mReplyHeader.responseCode != ResponseCodes.OBEX_HTTP_CONTINUE)) {
1779439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            throw new IOException("Operation has already ended");
1789439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        }
1799439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
1803998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun        mExceptionMessage = "Operation aborted";
1813998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun        if ((!mOperationDone) && (mReplyHeader.responseCode == ResponseCodes.OBEX_HTTP_CONTINUE)) {
1823998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun            mOperationDone = true;
1839439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            /*
1849439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly             * Since we are not sending any headers or returning any headers then
1859439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly             * we just need to write and read the same bytes
1869439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly             */
187238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde            mParent.sendRequest(ObexHelper.OBEX_OPCODE_ABORT, null, mReplyHeader, null, false);
1889439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
1893998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun            if (mReplyHeader.responseCode != ResponseCodes.OBEX_HTTP_OK) {
1909439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                throw new IOException("Invalid response code from server");
1919439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            }
1929439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
1933998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun            mExceptionMessage = null;
1949439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        }
1959439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
1969439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        close();
1979439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    }
1989439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
1999439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    /**
20005ff98bbefda39b9ff26f8bca132cfd0248745c6Tao Liejun     * Retrieves the response code retrieved from the server. Response codes are
20105ff98bbefda39b9ff26f8bca132cfd0248745c6Tao Liejun     * defined in the <code>ResponseCodes</code> interface.
2029439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     * @return the response code retrieved from the server
2032e0da96e757a977154063f980d3f4e1abd41cf09Nick Pelly     * @throws IOException if an error occurred in the transport layer during
20405ff98bbefda39b9ff26f8bca132cfd0248745c6Tao Liejun     *         the transaction; if this method is called on a
20505ff98bbefda39b9ff26f8bca132cfd0248745c6Tao Liejun     *         <code>HeaderSet</code> object created by calling
20605ff98bbefda39b9ff26f8bca132cfd0248745c6Tao Liejun     *         <code>createHeaderSet</code> in a <code>ClientSession</code>
20705ff98bbefda39b9ff26f8bca132cfd0248745c6Tao Liejun     *         object
2089439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     */
2099439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    public synchronized int getResponseCode() throws IOException {
2103998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun        if ((mReplyHeader.responseCode == -1)
2113998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun                || (mReplyHeader.responseCode == ResponseCodes.OBEX_HTTP_CONTINUE)) {
2129439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            validateConnection();
2139439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        }
2149439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
2153998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun        return mReplyHeader.responseCode;
2169439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    }
2179439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
2189439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    /**
2199439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     * This method will always return <code>null</code>
2209439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     * @return <code>null</code>
2219439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     */
2229439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    public String getEncoding() {
2239439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        return null;
2249439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    }
2259439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
2269439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    /**
2279439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     * Returns the type of content that the resource connected to is providing.
2289439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     * E.g. if the connection is via HTTP, then the value of the content-type
2299439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     * header field is returned.
2309439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     * @return the content type of the resource that the URL references, or
23105ff98bbefda39b9ff26f8bca132cfd0248745c6Tao Liejun     *         <code>null</code> if not known
2329439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     */
2339439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    public String getType() {
2349439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        try {
2353998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun            return (String)mReplyHeader.getHeader(HeaderSet.TYPE);
2369439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        } catch (IOException e) {
237238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde            if(V) Log.d(TAG, "Exception occured - returning null",e);
2389439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            return null;
2399439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        }
2409439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    }
2419439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
2429439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    /**
2439439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     * Returns the length of the content which is being provided. E.g. if the
24405ff98bbefda39b9ff26f8bca132cfd0248745c6Tao Liejun     * connection is via HTTP, then the value of the content-length header field
24505ff98bbefda39b9ff26f8bca132cfd0248745c6Tao Liejun     * is returned.
2469439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     * @return the content length of the resource that this connection's URL
24705ff98bbefda39b9ff26f8bca132cfd0248745c6Tao Liejun     *         references, or -1 if the content length is not known
2489439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     */
2499439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    public long getLength() {
2509439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        try {
2513998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun            Long temp = (Long)mReplyHeader.getHeader(HeaderSet.LENGTH);
2529439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
2539439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            if (temp == null) {
2549439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                return -1;
2559439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            } else {
2569439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                return temp.longValue();
2579439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            }
2589439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        } catch (IOException e) {
259238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde            if(V) Log.d(TAG,"Exception occured - returning -1",e);
2609439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            return -1;
2619439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        }
2629439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    }
2639439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
2649439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    /**
2659439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     * Open and return an input stream for a connection.
2669439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     * @return an input stream
2672e0da96e757a977154063f980d3f4e1abd41cf09Nick Pelly     * @throws IOException if an I/O error occurs
2689439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     */
2699439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    public InputStream openInputStream() throws IOException {
2709439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
2719439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        ensureOpen();
2729439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
2733998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun        if (mPrivateInputOpen)
2749439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            throw new IOException("no more input streams available");
2753998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun        if (mGetOperation) {
2769439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            // send the GET request here
2779439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            validateConnection();
2789439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        } else {
2793998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun            if (mPrivateInput == null) {
2803998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun                mPrivateInput = new PrivateInputStream(this);
2819439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            }
2829439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        }
2839439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
2843998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun        mPrivateInputOpen = true;
2859439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
2863998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun        return mPrivateInput;
2879439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    }
2889439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
28905ff98bbefda39b9ff26f8bca132cfd0248745c6Tao Liejun    /**
2909439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     * Open and return a data input stream for a connection.
2919439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     * @return an input stream
2922e0da96e757a977154063f980d3f4e1abd41cf09Nick Pelly     * @throws IOException if an I/O error occurs
2939439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     */
2949439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    public DataInputStream openDataInputStream() throws IOException {
2959439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        return new DataInputStream(openInputStream());
2969439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    }
2979439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
2989439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    /**
2999439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     * Open and return an output stream for a connection.
3009439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     * @return an output stream
3012e0da96e757a977154063f980d3f4e1abd41cf09Nick Pelly     * @throws IOException if an I/O error occurs
3029439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     */
3039439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    public OutputStream openOutputStream() throws IOException {
3043998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun
3059439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        ensureOpen();
3069439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        ensureNotDone();
3079439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
3083998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun        if (mPrivateOutputOpen)
3099439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            throw new IOException("no more output streams available");
3109439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
3113998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun        if (mPrivateOutput == null) {
3129439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            // there are 3 bytes operation headers and 3 bytes body headers //
31365208317ba9d16486b47ebcaa868c596d424c87fLixin Yue            mPrivateOutput = new PrivateOutputStream(this, getMaxPacketSize());
3149439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        }
3159439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
3163998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun        mPrivateOutputOpen = true;
3179439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
3183998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun        return mPrivateOutput;
3199439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    }
3209439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
3219439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    public int getMaxPacketSize() {
32265208317ba9d16486b47ebcaa868c596d424c87fLixin Yue        return mMaxPacketSize - 6 - getHeaderLength();
32365208317ba9d16486b47ebcaa868c596d424c87fLixin Yue    }
32465208317ba9d16486b47ebcaa868c596d424c87fLixin Yue
32565208317ba9d16486b47ebcaa868c596d424c87fLixin Yue    public int getHeaderLength() {
32665208317ba9d16486b47ebcaa868c596d424c87fLixin Yue        // OPP may need it
32765208317ba9d16486b47ebcaa868c596d424c87fLixin Yue        byte[] headerArray = ObexHelper.createHeader(mRequestHeader, false);
32865208317ba9d16486b47ebcaa868c596d424c87fLixin Yue        return headerArray.length;
3299439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    }
3309439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
3319439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    /**
3329439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     * Open and return a data output stream for a connection.
3339439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     * @return an output stream
3342e0da96e757a977154063f980d3f4e1abd41cf09Nick Pelly     * @throws IOException if an I/O error occurs
3359439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     */
3369439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    public DataOutputStream openDataOutputStream() throws IOException {
3379439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        return new DataOutputStream(openOutputStream());
3389439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    }
3399439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
3409439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    /**
3419439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     * Closes the connection and ends the transaction
3422e0da96e757a977154063f980d3f4e1abd41cf09Nick Pelly     * @throws IOException if the operation has already ended or is closed
3439439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     */
3449439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    public void close() throws IOException {
3453998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun        mInputOpen = false;
3463998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun        mPrivateInputOpen = false;
3473998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun        mPrivateOutputOpen = false;
3483998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun        mParent.setRequestInactive();
3499439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    }
3509439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
3519439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    /**
3529439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     * Returns the headers that have been received during the operation.
35305ff98bbefda39b9ff26f8bca132cfd0248745c6Tao Liejun     * Modifying the object returned has no effect on the headers that are sent
35405ff98bbefda39b9ff26f8bca132cfd0248745c6Tao Liejun     * or retrieved.
3559439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     * @return the headers received during this <code>Operation</code>
3562e0da96e757a977154063f980d3f4e1abd41cf09Nick Pelly     * @throws IOException if this <code>Operation</code> has been closed
3579439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     */
3583998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun    public HeaderSet getReceivedHeader() throws IOException {
3599439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        ensureOpen();
3609439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
3613998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun        return mReplyHeader;
3629439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    }
3639439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
3649439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    /**
3659439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     * Specifies the headers that should be sent in the next OBEX message that
3669439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     * is sent.
3679439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     * @param headers the headers to send in the next message
36805ff98bbefda39b9ff26f8bca132cfd0248745c6Tao Liejun     * @throws IOException if this <code>Operation</code> has been closed or the
36905ff98bbefda39b9ff26f8bca132cfd0248745c6Tao Liejun     *         transaction has ended and no further messages will be exchanged
3702e0da96e757a977154063f980d3f4e1abd41cf09Nick Pelly     * @throws IllegalArgumentException if <code>headers</code> was not created
37105ff98bbefda39b9ff26f8bca132cfd0248745c6Tao Liejun     *         by a call to <code>ServerRequestHandler.createHeaderSet()</code>
3722e0da96e757a977154063f980d3f4e1abd41cf09Nick Pelly     * @throws NullPointerException if <code>headers</code> is <code>null</code>
3739439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     */
3749439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    public void sendHeaders(HeaderSet headers) throws IOException {
3759439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        ensureOpen();
3763998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun        if (mOperationDone) {
3779439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            throw new IOException("Operation has already exchanged all data");
3789439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        }
3799439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
3809439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        if (headers == null) {
3813998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun            throw new IOException("Headers may not be null");
3829439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        }
3839439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
3849439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        int[] headerList = headers.getHeaderList();
3859439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        if (headerList != null) {
3869439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            for (int i = 0; i < headerList.length; i++) {
3873998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun                mRequestHeader.setHeader(headerList[i], headers.getHeader(headerList[i]));
3889439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            }
3899439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        }
3909439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    }
3919439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
3929439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    /**
39305ff98bbefda39b9ff26f8bca132cfd0248745c6Tao Liejun     * Verifies that additional information may be sent. In other words, the
3949439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     * operation is not done.
3952e0da96e757a977154063f980d3f4e1abd41cf09Nick Pelly     * @throws IOException if the operation is completed
3969439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     */
3979439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    public void ensureNotDone() throws IOException {
3983998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun        if (mOperationDone) {
3999439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            throw new IOException("Operation has completed");
4009439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        }
4019439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    }
4029439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
4039439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    /**
4049439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     * Verifies that the connection is open and no exceptions should be thrown.
4052e0da96e757a977154063f980d3f4e1abd41cf09Nick Pelly     * @throws IOException if an exception needs to be thrown
4069439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     */
4079439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    public void ensureOpen() throws IOException {
4083998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun        mParent.ensureOpen();
4099439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
4103998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun        if (mExceptionMessage != null) {
4113998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun            throw new IOException(mExceptionMessage);
4129439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        }
4133998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun        if (!mInputOpen) {
4149439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            throw new IOException("Operation has already ended");
4159439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        }
4169439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    }
4179439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
4189439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    /**
4199439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     * Verifies that the connection is open and the proper data has been read.
4202e0da96e757a977154063f980d3f4e1abd41cf09Nick Pelly     * @throws IOException if an IO error occurs
4219439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     */
4229439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    private void validateConnection() throws IOException {
4239439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        ensureOpen();
4249439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
425f8c2ad085b5380ec226ba12b808511cf519e6ce6Ajay Panicker        // Make sure that a response has been recieved from remote
426f8c2ad085b5380ec226ba12b808511cf519e6ce6Ajay Panicker        // before continuing
427f8c2ad085b5380ec226ba12b808511cf519e6ce6Ajay Panicker        if (mPrivateInput == null || mReplyHeader.responseCode == -1) {
4289439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            startProcessing();
4299439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        }
4309439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    }
4319439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
4329439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    /**
433238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde     * Sends a request to the client of the specified type.
434238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde     * This function will enable SRM and set SRM active if the server
435238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde     * response allows this.
43605ff98bbefda39b9ff26f8bca132cfd0248745c6Tao Liejun     * @param opCode the request code to send to the client
4379439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     * @return <code>true</code> if there is more data to send;
43805ff98bbefda39b9ff26f8bca132cfd0248745c6Tao Liejun     *         <code>false</code> if there is no more data to send
4392e0da96e757a977154063f980d3f4e1abd41cf09Nick Pelly     * @throws IOException if an IO error occurs
4409439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     */
44105ff98bbefda39b9ff26f8bca132cfd0248745c6Tao Liejun    private boolean sendRequest(int opCode) throws IOException {
4429439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        boolean returnValue = false;
4439439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        ByteArrayOutputStream out = new ByteArrayOutputStream();
4449439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        int bodyLength = -1;
4453998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun        byte[] headerArray = ObexHelper.createHeader(mRequestHeader, true);
4463998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun        if (mPrivateOutput != null) {
4473998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun            bodyLength = mPrivateOutput.size();
4489439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        }
4499439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
4509439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        /*
4519439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly         * Determine if there is space to add a body request.  At present
4529439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly         * this method checks to see if there is room for at least a 17
4539439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly         * byte body header.  This number needs to be at least 6 so that
4549439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly         * there is room for the header ID and length and the reply ID and
4559439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly         * length, but it is a waste of resources if we can't send much of
4569439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly         * the body.
4579439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly         */
458238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde        final int MINIMUM_BODY_LENGTH = 3;
459238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde        if ((ObexHelper.BASE_PACKET_LENGTH + headerArray.length + MINIMUM_BODY_LENGTH)
460238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde                > mMaxPacketSize) {
4619439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            int end = 0;
4629439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            int start = 0;
4639439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            // split & send the headerArray in multiple packets.
4649439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
4659439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            while (end != headerArray.length) {
4669439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                //split the headerArray
467238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde
4683998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun                end = ObexHelper.findHeaderEnd(headerArray, start, mMaxPacketSize
4693998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun                        - ObexHelper.BASE_PACKET_LENGTH);
4700d376053747615ac7c4b45ab7810329ffbdf80d1Kim Schulz                // can not split
4719439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                if (end == -1) {
4723998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun                    mOperationDone = true;
4739439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                    abort();
4743998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun                    mExceptionMessage = "Header larger then can be sent in a packet";
4753998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun                    mInputOpen = false;
4769439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
4773998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun                    if (mPrivateInput != null) {
4783998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun                        mPrivateInput.close();
4799439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                    }
4809439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
4813998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun                    if (mPrivateOutput != null) {
4823998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun                        mPrivateOutput.close();
4839439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                    }
4849439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                    throw new IOException("OBEX Packet exceeds max packet size");
4859439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                }
4869439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
4879439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                byte[] sendHeader = new byte[end - start];
4889439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                System.arraycopy(headerArray, start, sendHeader, 0, sendHeader.length);
489238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde                if (!mParent.sendRequest(opCode, sendHeader, mReplyHeader, mPrivateInput, false)) {
4909439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                    return false;
4919439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                }
4929439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
4933998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun                if (mReplyHeader.responseCode != ResponseCodes.OBEX_HTTP_CONTINUE) {
4949439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                    return false;
4959439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                }
4969439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
4979439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                start = end;
4989439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            }
4999439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
500238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde            // Enable SRM if it should be enabled
501238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde            checkForSrm();
502238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde
5039439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            if (bodyLength > 0) {
5049439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                return true;
5059439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            } else {
5069439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                return false;
5079439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            }
5089439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        } else {
509238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde            /* All headers will fit into a single package */
510238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde            if(mSendBodyHeader == false) {
511238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde                /* As we are not to send any body data, set the FINAL_BIT */
512238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde                opCode |= ObexHelper.OBEX_OPCODE_FINAL_BIT_MASK;
513238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde            }
5149439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            out.write(headerArray);
5159439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        }
5169439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
5179439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        if (bodyLength > 0) {
5189439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            /*
5193998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun             * Determine if we can send the whole body or just part of
5209439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly             * the body.  Remember that there is the 3 bytes for the
5219439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly             * response message and 3 bytes for the header ID and length
5229439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly             */
5233998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun            if (bodyLength > (mMaxPacketSize - headerArray.length - 6)) {
5249439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                returnValue = true;
5259439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
5263998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun                bodyLength = mMaxPacketSize - headerArray.length - 6;
5279439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            }
5289439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
5293998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun            byte[] body = mPrivateOutput.readBytes(bodyLength);
5309439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
5319439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            /*
5329439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly             * Since this is a put request if the final bit is set or
5339439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly             * the output stream is closed we need to send the 0x49
5349439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly             * (End of Body) otherwise, we need to send 0x48 (Body)
5359439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly             */
5363998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun            if ((mPrivateOutput.isClosed()) && (!returnValue) && (!mEndOfBodySent)
537238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde                    && ((opCode & ObexHelper.OBEX_OPCODE_FINAL_BIT_MASK) != 0)) {
538238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde                out.write(HeaderSet.END_OF_BODY);
5393998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun                mEndOfBodySent = true;
5409439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            } else {
541238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde                out.write(HeaderSet.BODY);
5429439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            }
5439439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
5449439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            bodyLength += 3;
5459439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            out.write((byte)(bodyLength >> 8));
5469439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            out.write((byte)bodyLength);
5479439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
5489439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            if (body != null) {
5499439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                out.write(body);
5509439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            }
5519439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        }
5529439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
5533998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun        if (mPrivateOutputOpen && bodyLength <= 0 && !mEndOfBodySent) {
5549439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            // only 0x82 or 0x83 can send 0x49
555238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde            if ((opCode & ObexHelper.OBEX_OPCODE_FINAL_BIT_MASK) == 0) {
556238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde                out.write(HeaderSet.BODY);
5579439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            } else {
558238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde                out.write(HeaderSet.END_OF_BODY);
5593998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun                mEndOfBodySent = true;
5609439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            }
5619439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
5629439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            bodyLength = 3;
5639439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            out.write((byte)(bodyLength >> 8));
5649439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            out.write((byte)bodyLength);
5659439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        }
5669439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
5679439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        if (out.size() == 0) {
568238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde            if (!mParent.sendRequest(opCode, null, mReplyHeader, mPrivateInput, mSrmActive)) {
5699439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                return false;
5709439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            }
571238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde            // Enable SRM if it should be enabled
572238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde            checkForSrm();
5739439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            return returnValue;
5749439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        }
5759439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        if ((out.size() > 0)
576238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde                && (!mParent.sendRequest(opCode, out.toByteArray(),
577238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde                        mReplyHeader, mPrivateInput, mSrmActive))) {
5789439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            return false;
5799439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        }
580238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde        // Enable SRM if it should be enabled
581238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde        checkForSrm();
5829439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
5830d376053747615ac7c4b45ab7810329ffbdf80d1Kim Schulz        // send all of the output data in 0x48,
5849439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        // send 0x49 with empty body
5853998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun        if ((mPrivateOutput != null) && (mPrivateOutput.size() > 0))
5869439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            returnValue = true;
5879439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
5889439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        return returnValue;
5899439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    }
5909439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
591238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde    private void checkForSrm() throws IOException {
592238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde        Byte srmMode = (Byte)mReplyHeader.getHeader(HeaderSet.SINGLE_RESPONSE_MODE);
593238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde        if(mParent.isSrmSupported() == true && srmMode != null
594238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde                && srmMode == ObexHelper.OBEX_SRM_ENABLE) {
595238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde            mSrmEnabled = true;
596238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde        }
597238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde        /**
598238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde         * Call this only when a complete obex packet have been received.
599238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde         * (This is not optimal, but the current design is not really suited to
600238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde         * the way SRM is specified.)
601238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde         * The BT usage of SRM is not really safe - it assumes that the SRMP will fit
602238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde         * into every OBEX packet, hence if another header occupies the entire packet,
603238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde         * the scheme will not work - unlikely though.
604238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde         */
605238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde        if(mSrmEnabled) {
606238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde            mSrmWaitingForRemote = false;
607238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde            Byte srmp = (Byte)mReplyHeader.getHeader(HeaderSet.SINGLE_RESPONSE_MODE_PARAMETER);
608238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde            if(srmp != null && srmp == ObexHelper.OBEX_SRMP_WAIT) {
609238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde                mSrmWaitingForRemote = true;
610238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde                // Clear the wait header, as the absence of the header in the next packet
611238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde                // indicates don't wait anymore.
612238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde                mReplyHeader.setHeader(HeaderSet.SINGLE_RESPONSE_MODE_PARAMETER, null);
613238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde            }
614238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde        }
615238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde        if((mSrmWaitingForRemote == false) && (mSrmEnabled == true)) {
616238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde            mSrmActive = true;
617238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde        }
618238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde    }
619238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde
6209439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    /**
62105ff98bbefda39b9ff26f8bca132cfd0248745c6Tao Liejun     * This method starts the processing thread results. It will send the
62205ff98bbefda39b9ff26f8bca132cfd0248745c6Tao Liejun     * initial request. If the response takes more then one packet, a thread
6239439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     * will be started to handle additional requests
6242e0da96e757a977154063f980d3f4e1abd41cf09Nick Pelly     * @throws IOException if an IO error occurs
6259439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     */
6269439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    private synchronized void startProcessing() throws IOException {
6279439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
6283998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun        if (mPrivateInput == null) {
6293998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun            mPrivateInput = new PrivateInputStream(this);
6309439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        }
6319439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        boolean more = true;
6329439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
6333998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun        if (mGetOperation) {
6343998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun            if (!mOperationDone) {
635eed32008a8d818d2781314adc7eccd7376ccf8b0AnubhavGupta                if (!mGetFinalFlag) {
636eed32008a8d818d2781314adc7eccd7376ccf8b0AnubhavGupta                    mReplyHeader.responseCode = ResponseCodes.OBEX_HTTP_CONTINUE;
637eed32008a8d818d2781314adc7eccd7376ccf8b0AnubhavGupta                    while ((more) && (mReplyHeader.responseCode ==
638eed32008a8d818d2781314adc7eccd7376ccf8b0AnubhavGupta                            ResponseCodes.OBEX_HTTP_CONTINUE)) {
639eed32008a8d818d2781314adc7eccd7376ccf8b0AnubhavGupta                        more = sendRequest(ObexHelper.OBEX_OPCODE_GET);
640eed32008a8d818d2781314adc7eccd7376ccf8b0AnubhavGupta                    }
641eed32008a8d818d2781314adc7eccd7376ccf8b0AnubhavGupta                    // For GET we need to loop until all headers have been sent,
642eed32008a8d818d2781314adc7eccd7376ccf8b0AnubhavGupta                    // And then we wait for the first continue package with the
643eed32008a8d818d2781314adc7eccd7376ccf8b0AnubhavGupta                    // reply.
644eed32008a8d818d2781314adc7eccd7376ccf8b0AnubhavGupta                    if (mReplyHeader.responseCode == ResponseCodes.OBEX_HTTP_CONTINUE) {
645eed32008a8d818d2781314adc7eccd7376ccf8b0AnubhavGupta                        mParent.sendRequest(ObexHelper.OBEX_OPCODE_GET_FINAL,
646eed32008a8d818d2781314adc7eccd7376ccf8b0AnubhavGupta                                null, mReplyHeader, mPrivateInput, mSrmActive);
647eed32008a8d818d2781314adc7eccd7376ccf8b0AnubhavGupta                    }
648eed32008a8d818d2781314adc7eccd7376ccf8b0AnubhavGupta                    if (mReplyHeader.responseCode != ResponseCodes.OBEX_HTTP_CONTINUE) {
649eed32008a8d818d2781314adc7eccd7376ccf8b0AnubhavGupta                        mOperationDone = true;
650eed32008a8d818d2781314adc7eccd7376ccf8b0AnubhavGupta                    } else {
651eed32008a8d818d2781314adc7eccd7376ccf8b0AnubhavGupta                        checkForSrm();
652eed32008a8d818d2781314adc7eccd7376ccf8b0AnubhavGupta                    }
653238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde                } else {
654eed32008a8d818d2781314adc7eccd7376ccf8b0AnubhavGupta                    more = sendRequest(ObexHelper.OBEX_OPCODE_GET_FINAL);
655eed32008a8d818d2781314adc7eccd7376ccf8b0AnubhavGupta
656eed32008a8d818d2781314adc7eccd7376ccf8b0AnubhavGupta                    if (more) {
657eed32008a8d818d2781314adc7eccd7376ccf8b0AnubhavGupta                        throw new IOException("FINAL_GET forced, data didn't fit into one packet");
658eed32008a8d818d2781314adc7eccd7376ccf8b0AnubhavGupta                    }
659eed32008a8d818d2781314adc7eccd7376ccf8b0AnubhavGupta
660eed32008a8d818d2781314adc7eccd7376ccf8b0AnubhavGupta                    mOperationDone = true;
6619439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                }
6629439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            }
6639439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        } else {
664238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde            // PUT operation
6653998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun            if (!mOperationDone) {
6663998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun                mReplyHeader.responseCode = ResponseCodes.OBEX_HTTP_CONTINUE;
6673998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun                while ((more) && (mReplyHeader.responseCode == ResponseCodes.OBEX_HTTP_CONTINUE)) {
668238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde                    more = sendRequest(ObexHelper.OBEX_OPCODE_PUT);
6699439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                }
6709439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            }
6719439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
6723998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun            if (mReplyHeader.responseCode == ResponseCodes.OBEX_HTTP_CONTINUE) {
673238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde                mParent.sendRequest(ObexHelper.OBEX_OPCODE_PUT_FINAL,
674238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde                        null, mReplyHeader, mPrivateInput, mSrmActive);
6759439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            }
6769439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
6773998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun            if (mReplyHeader.responseCode != ResponseCodes.OBEX_HTTP_CONTINUE) {
6783998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun                mOperationDone = true;
6799439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            }
6809439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        }
6819439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    }
6829439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
6839439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    /**
6849439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     * Continues the operation since there is no data to read.
68505ff98bbefda39b9ff26f8bca132cfd0248745c6Tao Liejun     * @param sendEmpty <code>true</code> if the operation should send an empty
68605ff98bbefda39b9ff26f8bca132cfd0248745c6Tao Liejun     *        packet or not send anything if there is no data to send
68705ff98bbefda39b9ff26f8bca132cfd0248745c6Tao Liejun     * @param inStream <code>true</code> if the stream is input stream or is
68805ff98bbefda39b9ff26f8bca132cfd0248745c6Tao Liejun     *        output stream
6892e0da96e757a977154063f980d3f4e1abd41cf09Nick Pelly     * @throws IOException if an IO error occurs
6909439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     */
6919439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    public synchronized boolean continueOperation(boolean sendEmpty, boolean inStream)
6929439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            throws IOException {
6939439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
694238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde        // One path to the first put operation - the other one does not need to
695238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde        // handle SRM, as all will fit into one packet.
696238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde
6973998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun        if (mGetOperation) {
6983998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun            if ((inStream) && (!mOperationDone)) {
6999439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                // to deal with inputstream in get operation
700238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde                mParent.sendRequest(ObexHelper.OBEX_OPCODE_GET_FINAL,
701238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde                        null, mReplyHeader, mPrivateInput, mSrmActive);
7029439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                /*
7039439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                  * Determine if that was not the last packet in the operation
7049439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                  */
7053998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun                if (mReplyHeader.responseCode != ResponseCodes.OBEX_HTTP_CONTINUE) {
7063998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun                    mOperationDone = true;
707238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde                } else {
708238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde                    checkForSrm();
7099439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                }
7109439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
7119439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                return true;
7129439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
7133998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun            } else if ((!inStream) && (!mOperationDone)) {
7149439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                // to deal with outputstream in get operation
7159439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
7163998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun                if (mPrivateInput == null) {
7173998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun                    mPrivateInput = new PrivateInputStream(this);
7189439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                }
719eed32008a8d818d2781314adc7eccd7376ccf8b0AnubhavGupta
720eed32008a8d818d2781314adc7eccd7376ccf8b0AnubhavGupta                if (!mGetFinalFlag) {
721eed32008a8d818d2781314adc7eccd7376ccf8b0AnubhavGupta                    sendRequest(ObexHelper.OBEX_OPCODE_GET);
722eed32008a8d818d2781314adc7eccd7376ccf8b0AnubhavGupta                } else {
723eed32008a8d818d2781314adc7eccd7376ccf8b0AnubhavGupta                    sendRequest(ObexHelper.OBEX_OPCODE_GET_FINAL);
724eed32008a8d818d2781314adc7eccd7376ccf8b0AnubhavGupta                }
725eed32008a8d818d2781314adc7eccd7376ccf8b0AnubhavGupta                if (mReplyHeader.responseCode != ResponseCodes.OBEX_HTTP_CONTINUE) {
726eed32008a8d818d2781314adc7eccd7376ccf8b0AnubhavGupta                    mOperationDone = true;
727eed32008a8d818d2781314adc7eccd7376ccf8b0AnubhavGupta                }
7289439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                return true;
7299439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
7303998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun            } else if (mOperationDone) {
7319439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                return false;
7329439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            }
7339439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
7349439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        } else {
735238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde            // PUT operation
7363998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun            if ((!inStream) && (!mOperationDone)) {
7379439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                // to deal with outputstream in put operation
7383998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun                if (mReplyHeader.responseCode == -1) {
7393998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun                    mReplyHeader.responseCode = ResponseCodes.OBEX_HTTP_CONTINUE;
7409439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                }
741238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde                sendRequest(ObexHelper.OBEX_OPCODE_PUT);
7429439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                return true;
7433998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun            } else if ((inStream) && (!mOperationDone)) {
7449439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                // How to deal with inputstream  in put operation ?
7459439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                return false;
7469439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
7473998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun            } else if (mOperationDone) {
7489439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                return false;
7499439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            }
7509439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
7519439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        }
7529439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        return false;
7539439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    }
7549439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
7559439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    /**
7569439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     * Called when the output or input stream is closed.
7579439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     * @param inStream <code>true</code> if the input stream is closed;
75805ff98bbefda39b9ff26f8bca132cfd0248745c6Tao Liejun     *        <code>false</code> if the output stream is closed
7592e0da96e757a977154063f980d3f4e1abd41cf09Nick Pelly     * @throws IOException if an IO error occurs
7609439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     */
7619439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    public void streamClosed(boolean inStream) throws IOException {
7623998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun        if (!mGetOperation) {
7633998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun            if ((!inStream) && (!mOperationDone)) {
7649439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                // to deal with outputstream in put operation
7659439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
7669439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                boolean more = true;
7679439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
7683998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun                if ((mPrivateOutput != null) && (mPrivateOutput.size() <= 0)) {
7693998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun                    byte[] headerArray = ObexHelper.createHeader(mRequestHeader, false);
7709439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                    if (headerArray.length <= 0)
7719439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                        more = false;
7729439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                }
7739439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                // If have not sent any data so send  all now
7743998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun                if (mReplyHeader.responseCode == -1) {
7753998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun                    mReplyHeader.responseCode = ResponseCodes.OBEX_HTTP_CONTINUE;
7769439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                }
7779439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
7783998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun                while ((more) && (mReplyHeader.responseCode == ResponseCodes.OBEX_HTTP_CONTINUE)) {
779238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde                    more = sendRequest(ObexHelper.OBEX_OPCODE_PUT);
7809439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                }
7819439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
7829439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                /*
7839439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                 * According to the IrOBEX specification, after the final put, you
7849439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                 * only have a single reply to send.  so we don't need the while
7859439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                 * loop.
7869439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                 */
7873998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun                while (mReplyHeader.responseCode == ResponseCodes.OBEX_HTTP_CONTINUE) {
7889439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
789238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde                    sendRequest(ObexHelper.OBEX_OPCODE_PUT_FINAL);
7909439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                }
7913998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun                mOperationDone = true;
7923998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun            } else if ((inStream) && (mOperationDone)) {
7939439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                // how to deal with input stream in put stream ?
7943998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun                mOperationDone = true;
7959439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            }
7969439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        } else {
7973998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun            if ((inStream) && (!mOperationDone)) {
7989439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
7999439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                // to deal with inputstream in get operation
8009439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                // Have not sent any data so send it all now
8019439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
8023998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun                if (mReplyHeader.responseCode == -1) {
8033998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun                    mReplyHeader.responseCode = ResponseCodes.OBEX_HTTP_CONTINUE;
8049439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                }
8059439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
80650ba032f4a81155c5f10561d39a4f258a0e4f244Hemant Gupta                while (mReplyHeader.responseCode == ResponseCodes.OBEX_HTTP_CONTINUE && !mOperationDone) {
807238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde                    if (!sendRequest(ObexHelper.OBEX_OPCODE_GET_FINAL)) {
8089439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                        break;
8099439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                    }
8109439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                }
81150ba032f4a81155c5f10561d39a4f258a0e4f244Hemant Gupta                while (mReplyHeader.responseCode == ResponseCodes.OBEX_HTTP_CONTINUE && !mOperationDone) {
812238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde                    mParent.sendRequest(ObexHelper.OBEX_OPCODE_GET_FINAL, null,
813238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde                            mReplyHeader, mPrivateInput, false);
814238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde                    // Regardless of the SRM state, wait for the response.
8159439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                }
8163998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun                mOperationDone = true;
8173998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun            } else if ((!inStream) && (!mOperationDone)) {
8189439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                // to deal with outputstream in get operation
8199439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                // part of the data may have been sent in continueOperation.
8209439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
8219439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                boolean more = true;
8229439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
8233998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun                if ((mPrivateOutput != null) && (mPrivateOutput.size() <= 0)) {
8243998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun                    byte[] headerArray = ObexHelper.createHeader(mRequestHeader, false);
8259439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                    if (headerArray.length <= 0)
8269439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                        more = false;
8279439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                }
8289439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
8293998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun                if (mPrivateInput == null) {
8303998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun                    mPrivateInput = new PrivateInputStream(this);
8319439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                }
8323998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun                if ((mPrivateOutput != null) && (mPrivateOutput.size() <= 0))
8339439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                    more = false;
8349439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
8353998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun                mReplyHeader.responseCode = ResponseCodes.OBEX_HTTP_CONTINUE;
8363998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun                while ((more) && (mReplyHeader.responseCode == ResponseCodes.OBEX_HTTP_CONTINUE)) {
837238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde                    more = sendRequest(ObexHelper.OBEX_OPCODE_GET);
8389439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                }
839238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde                sendRequest(ObexHelper.OBEX_OPCODE_GET_FINAL);
8409439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                //                parent.sendRequest(0x83, null, replyHeaders, privateInput);
8413998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun                if (mReplyHeader.responseCode != ResponseCodes.OBEX_HTTP_CONTINUE) {
8423998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun                    mOperationDone = true;
8439439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                }
8449439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            }
8459439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        }
8469439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    }
847fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie
848fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie    public void noBodyHeader(){
849238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde        mSendBodyHeader = false;
850fe3807a5b23f54f6539436d71aa0cd931a2b76f0Matthew Xie    }
8519439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly}
852