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