diff --git a/obex/Android.bp b/obex/Android.bp index 37e7f76bead5..d89d41de2895 100644 --- a/obex/Android.bp +++ b/obex/Android.bp @@ -44,6 +44,8 @@ license { ], } +// No longer used. Only kept because the ObexPacket class is a public API. +// The library has been migrated to platform/external/obex. java_sdk_library { name: "javax.obex", srcs: ["javax/**/*.java"], diff --git a/obex/javax/obex/ApplicationParameter.java b/obex/javax/obex/ApplicationParameter.java deleted file mode 100644 index 16770a1aef31..000000000000 --- a/obex/javax/obex/ApplicationParameter.java +++ /dev/null @@ -1,162 +0,0 @@ -/* - * Copyright (c) 2008-2009, Motorola, Inc. - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * - Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * - Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * - Neither the name of the Motorola, Inc. nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -package javax.obex; - -/** - * @hide - */ -public final class ApplicationParameter { - - private byte[] mArray; - - private int mLength; - - private int mMaxLength = 1000; - - public static class TRIPLET_TAGID { - public static final byte ORDER_TAGID = 0x01; - - public static final byte SEARCH_VALUE_TAGID = 0x02; - - public static final byte SEARCH_ATTRIBUTE_TAGID = 0x03; - - // if equals to "0", PSE only reply number of contacts - public static final byte MAXLISTCOUNT_TAGID = 0x04; - - public static final byte LISTSTARTOFFSET_TAGID = 0x05; - - public static final byte PROPERTY_SELECTOR_TAGID = 0x06; - - public static final byte FORMAT_TAGID = 0x07; - - // only used if max list count = 0 - public static final byte PHONEBOOKSIZE_TAGID = 0x08; - - // only used in "mch" in response - public static final byte NEWMISSEDCALLS_TAGID = 0x09; - - public static final byte SUPPORTEDFEATURE_TAGID = 0x10; - - public static final byte PRIMARYVERSIONCOUNTER_TAGID = 0x0A; - - public static final byte SECONDARYVERSIONCOUNTER_TAGID = 0x0B; - - public static final byte VCARDSELECTOR_TAGID = 0x0C; - - public static final byte DATABASEIDENTIFIER_TAGID = 0x0D; - - public static final byte VCARDSELECTOROPERATOR_TAGID = 0x0E; - - public static final byte RESET_NEW_MISSED_CALLS_TAGID = 0x0F; - } - - public static class TRIPLET_VALUE { - public static class ORDER { - public static final byte ORDER_BY_INDEX = 0x00; - - public static final byte ORDER_BY_ALPHANUMERIC = 0x01; - - public static final byte ORDER_BY_PHONETIC = 0x02; - } - - public static class SEARCHATTRIBUTE { - public static final byte SEARCH_BY_NAME = 0x00; - - public static final byte SEARCH_BY_NUMBER = 0x01; - - public static final byte SEARCH_BY_SOUND = 0x02; - } - - public static class FORMAT { - public static final byte VCARD_VERSION_21 = 0x00; - - public static final byte VCARD_VERSION_30 = 0x01; - } - } - - public static class TRIPLET_LENGTH { - public static final byte ORDER_LENGTH = 1; - - public static final byte SEARCH_ATTRIBUTE_LENGTH = 1; - - public static final byte MAXLISTCOUNT_LENGTH = 2; - - public static final byte LISTSTARTOFFSET_LENGTH = 2; - - public static final byte PROPERTY_SELECTOR_LENGTH = 8; - - public static final byte FORMAT_LENGTH = 1; - - public static final byte PHONEBOOKSIZE_LENGTH = 2; - - public static final byte NEWMISSEDCALLS_LENGTH = 1; - - public static final byte SUPPORTEDFEATURE_LENGTH = 4; - - public static final byte PRIMARYVERSIONCOUNTER_LENGTH = 16; - - public static final byte SECONDARYVERSIONCOUNTER_LENGTH = 16; - - public static final byte VCARDSELECTOR_LENGTH = 8; - - public static final byte DATABASEIDENTIFIER_LENGTH = 16; - - public static final byte VCARDSELECTOROPERATOR_LENGTH = 1; - - public static final byte RESETNEWMISSEDCALLS_LENGTH = 1; - } - - public ApplicationParameter() { - mArray = new byte[mMaxLength]; - mLength = 0; - } - - public void addAPPHeader(byte tag, byte len, byte[] value) { - if ((mLength + len + 2) > mMaxLength) { - byte[] array_tmp = new byte[mLength + 4 * len]; - System.arraycopy(mArray, 0, array_tmp, 0, mLength); - mArray = array_tmp; - mMaxLength = mLength + 4 * len; - } - mArray[mLength++] = tag; - mArray[mLength++] = len; - System.arraycopy(value, 0, mArray, mLength, len); - mLength += len; - } - - public byte[] getAPPparam() { - byte[] para = new byte[mLength]; - System.arraycopy(mArray, 0, para, 0, mLength); - return para; - } -} diff --git a/obex/javax/obex/Authenticator.java b/obex/javax/obex/Authenticator.java deleted file mode 100644 index ec226fb7ada3..000000000000 --- a/obex/javax/obex/Authenticator.java +++ /dev/null @@ -1,115 +0,0 @@ -/* - * Copyright (c) 2008-2009, Motorola, Inc. - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * - Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * - Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * - Neither the name of the Motorola, Inc. nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -package javax.obex; - -/** - * This interface provides a way to respond to authentication challenge and - * authentication response headers. When a client or server receives an - * authentication challenge or authentication response header, the - * onAuthenticationChallenge() or - * onAuthenticationResponse() will be called, respectively, by the - * implementation. - *

- * For more information on how the authentication procedure works in OBEX, - * please review the IrOBEX specification at http://www.irda.org. - *

- * Authentication Challenges - *

- * When a client or server receives an authentication challenge header, the - * onAuthenticationChallenge() method will be invoked by the OBEX - * API implementation. The application will then return the user name (if - * needed) and password via a PasswordAuthentication object. The - * password in this object is not sent in the authentication response. Instead, - * the 16-byte challenge received in the authentication challenge is combined - * with the password returned from the onAuthenticationChallenge() - * method and passed through the MD5 hash algorithm. The resulting value is sent - * in the authentication response along with the user name if it was provided. - *

- * Authentication Responses - *

- * When a client or server receives an authentication response header, the - * onAuthenticationResponse() method is invoked by the API - * implementation with the user name received in the authentication response - * header. (The user name will be null if no user name was provided - * in the authentication response header.) The application must determine the - * correct password. This value should be returned from the - * onAuthenticationResponse() method. If the authentication request - * should fail without the implementation checking the password, - * null should be returned by the application. (This is needed for - * reasons like not recognizing the user name, etc.) If the returned value is - * not null, the OBEX API implementation will combine the password - * returned from the onAuthenticationResponse() method and - * challenge sent via the authentication challenge, apply the MD5 hash - * algorithm, and compare the result to the response hash received in the - * authentication response header. If the values are not equal, an - * IOException will be thrown if the client requested - * authentication. If the server requested authentication, the - * onAuthenticationFailure() method will be called on the - * ServerRequestHandler that failed authentication. The connection - * is not closed if authentication failed. - * @hide - */ -public interface Authenticator { - - /** - * Called when a client or a server receives an authentication challenge - * header. It should respond to the challenge with a - * PasswordAuthentication that contains the correct user name - * and password for the challenge. - * @param description the description of which user name and password should - * be used; if no description is provided in the authentication - * challenge or the description is encoded in an encoding scheme that - * is not supported, an empty string will be provided - * @param isUserIdRequired true if the user ID is required; - * false if the user ID is not required - * @param isFullAccess true if full access to the server will - * be granted; false if read only access will be granted - * @return a PasswordAuthentication object containing the user - * name and password used for authentication - */ - PasswordAuthentication onAuthenticationChallenge(String description, boolean isUserIdRequired, - boolean isFullAccess); - - /** - * Called when a client or server receives an authentication response - * header. This method will provide the user name and expect the correct - * password to be returned. - * @param userName the user name provided in the authentication response; may - * be null - * @return the correct password for the user name provided; if - * null is returned then the authentication request - * failed - */ - byte[] onAuthenticationResponse(byte[] userName); -} diff --git a/obex/javax/obex/BaseStream.java b/obex/javax/obex/BaseStream.java deleted file mode 100644 index 022ad4fb4a34..000000000000 --- a/obex/javax/obex/BaseStream.java +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright (c) 2008-2009, Motorola, Inc. - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * - Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * - Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * - Neither the name of the Motorola, Inc. nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -package javax.obex; - -import java.io.IOException; - -/** - * This interface defines the methods needed by a parent that uses the - * PrivateInputStream and PrivateOutputStream objects defined in this package. - * @hide - */ -public interface BaseStream { - - /** - * Verifies that this object is still open. - * @throws IOException if the object is closed - */ - void ensureOpen() throws IOException; - - /** - * Verifies that additional information may be sent. In other words, the - * operation is not done. - * @throws IOException if the operation is completed - */ - void ensureNotDone() throws IOException; - - /** - * Continues the operation since there is no data to read. - * @param sendEmpty true if the operation should send an empty - * packet or not send anything if there is no data to send - * @param inStream true if the stream is input stream or is - * output stream - * @return true if the operation was completed; - * false if no operation took place - * @throws IOException if an IO error occurs - */ - boolean continueOperation(boolean sendEmpty, boolean inStream) throws IOException; - - /** - * Called when the output or input stream is closed. - * @param inStream true if the input stream is closed; - * false if the output stream is closed - * @throws IOException if an IO error occurs - */ - void streamClosed(boolean inStream) throws IOException; -} diff --git a/obex/javax/obex/ClientOperation.java b/obex/javax/obex/ClientOperation.java deleted file mode 100644 index c627dfb8abac..000000000000 --- a/obex/javax/obex/ClientOperation.java +++ /dev/null @@ -1,851 +0,0 @@ -/* - * Copyright (c) 2015 The Android Open Source Project - * Copyright (C) 2015 Samsung LSI - * Copyright (c) 2008-2009, Motorola, Inc. - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * - Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * - Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * - Neither the name of the Motorola, Inc. nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -package javax.obex; - -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.io.DataInputStream; -import java.io.DataOutputStream; -import java.io.ByteArrayOutputStream; - -import android.util.Log; - -/** - * This class implements the Operation interface. It will read and - * write data via puts and gets. - * @hide - */ -public final class ClientOperation implements Operation, BaseStream { - - private static final String TAG = "ClientOperation"; - - private static final boolean V = ObexHelper.VDBG; - - private ClientSession mParent; - - private boolean mInputOpen; - - private PrivateInputStream mPrivateInput; - - private boolean mPrivateInputOpen; - - private PrivateOutputStream mPrivateOutput; - - private boolean mPrivateOutputOpen; - - private String mExceptionMessage; - - private int mMaxPacketSize; - - private boolean mOperationDone; - - private boolean mGetOperation; - - private boolean mGetFinalFlag; - - private HeaderSet mRequestHeader; - - private HeaderSet mReplyHeader; - - private boolean mEndOfBodySent; - - private boolean mSendBodyHeader = true; - // A latch - when triggered, there is not way back ;-) - private boolean mSrmActive = false; - - // Assume SRM disabled - until support is confirmed - // by the server - private boolean mSrmEnabled = false; - // keep waiting until final-bit is received in request - // to handle the case where the SRM enable header is in - // a different OBEX packet than the SRMP header. - private boolean mSrmWaitingForRemote = true; - - - /** - * Creates new OperationImpl to read and write data to a server - * @param maxSize the maximum packet size - * @param p the parent to this object - * @param type true if this is a get request; - * falseResponseCodes interface. - * @return the response code retrieved from the server - * @throws IOException if an error occurred in the transport layer during - * the transaction; if this method is called on a - * HeaderSet object created by calling - * createHeaderSet in a ClientSession - * object - */ - public synchronized int getResponseCode() throws IOException { - if ((mReplyHeader.responseCode == -1) - || (mReplyHeader.responseCode == ResponseCodes.OBEX_HTTP_CONTINUE)) { - validateConnection(); - } - - return mReplyHeader.responseCode; - } - - /** - * This method will always return null - * @return null - */ - public String getEncoding() { - return null; - } - - /** - * Returns the type of content that the resource connected to is providing. - * E.g. if the connection is via HTTP, then the value of the content-type - * header field is returned. - * @return the content type of the resource that the URL references, or - * null if not known - */ - public String getType() { - try { - return (String)mReplyHeader.getHeader(HeaderSet.TYPE); - } catch (IOException e) { - if(V) Log.d(TAG, "Exception occured - returning null",e); - return null; - } - } - - /** - * Returns the length of the content which is being provided. E.g. if the - * connection is via HTTP, then the value of the content-length header field - * is returned. - * @return the content length of the resource that this connection's URL - * references, or -1 if the content length is not known - */ - public long getLength() { - try { - Long temp = (Long)mReplyHeader.getHeader(HeaderSet.LENGTH); - - if (temp == null) { - return -1; - } else { - return temp.longValue(); - } - } catch (IOException e) { - if(V) Log.d(TAG,"Exception occured - returning -1",e); - return -1; - } - } - - /** - * Open and return an input stream for a connection. - * @return an input stream - * @throws IOException if an I/O error occurs - */ - public InputStream openInputStream() throws IOException { - - ensureOpen(); - - if (mPrivateInputOpen) - throw new IOException("no more input streams available"); - if (mGetOperation) { - // send the GET request here - validateConnection(); - } else { - if (mPrivateInput == null) { - mPrivateInput = new PrivateInputStream(this); - } - } - - mPrivateInputOpen = true; - - return mPrivateInput; - } - - /** - * Open and return a data input stream for a connection. - * @return an input stream - * @throws IOException if an I/O error occurs - */ - public DataInputStream openDataInputStream() throws IOException { - return new DataInputStream(openInputStream()); - } - - /** - * Open and return an output stream for a connection. - * @return an output stream - * @throws IOException if an I/O error occurs - */ - public OutputStream openOutputStream() throws IOException { - - ensureOpen(); - ensureNotDone(); - - if (mPrivateOutputOpen) - throw new IOException("no more output streams available"); - - if (mPrivateOutput == null) { - // there are 3 bytes operation headers and 3 bytes body headers // - mPrivateOutput = new PrivateOutputStream(this, getMaxPacketSize()); - } - - mPrivateOutputOpen = true; - - return mPrivateOutput; - } - - public int getMaxPacketSize() { - return mMaxPacketSize - 6 - getHeaderLength(); - } - - public int getHeaderLength() { - // OPP may need it - byte[] headerArray = ObexHelper.createHeader(mRequestHeader, false); - return headerArray.length; - } - - /** - * Open and return a data output stream for a connection. - * @return an output stream - * @throws IOException if an I/O error occurs - */ - public DataOutputStream openDataOutputStream() throws IOException { - return new DataOutputStream(openOutputStream()); - } - - /** - * Closes the connection and ends the transaction - * @throws IOException if the operation has already ended or is closed - */ - public void close() throws IOException { - mInputOpen = false; - mPrivateInputOpen = false; - mPrivateOutputOpen = false; - mParent.setRequestInactive(); - } - - /** - * Returns the headers that have been received during the operation. - * Modifying the object returned has no effect on the headers that are sent - * or retrieved. - * @return the headers received during this Operation - * @throws IOException if this Operation has been closed - */ - public HeaderSet getReceivedHeader() throws IOException { - ensureOpen(); - - return mReplyHeader; - } - - /** - * Specifies the headers that should be sent in the next OBEX message that - * is sent. - * @param headers the headers to send in the next message - * @throws IOException if this Operation has been closed or the - * transaction has ended and no further messages will be exchanged - * @throws IllegalArgumentException if headers was not created - * by a call to ServerRequestHandler.createHeaderSet() - * @throws NullPointerException if headers is null - */ - public void sendHeaders(HeaderSet headers) throws IOException { - ensureOpen(); - if (mOperationDone) { - throw new IOException("Operation has already exchanged all data"); - } - - if (headers == null) { - throw new IOException("Headers may not be null"); - } - - int[] headerList = headers.getHeaderList(); - if (headerList != null) { - for (int i = 0; i < headerList.length; i++) { - mRequestHeader.setHeader(headerList[i], headers.getHeader(headerList[i])); - } - } - } - - /** - * Verifies that additional information may be sent. In other words, the - * operation is not done. - * @throws IOException if the operation is completed - */ - public void ensureNotDone() throws IOException { - if (mOperationDone) { - throw new IOException("Operation has completed"); - } - } - - /** - * Verifies that the connection is open and no exceptions should be thrown. - * @throws IOException if an exception needs to be thrown - */ - public void ensureOpen() throws IOException { - mParent.ensureOpen(); - - if (mExceptionMessage != null) { - throw new IOException(mExceptionMessage); - } - if (!mInputOpen) { - throw new IOException("Operation has already ended"); - } - } - - /** - * Verifies that the connection is open and the proper data has been read. - * @throws IOException if an IO error occurs - */ - private void validateConnection() throws IOException { - ensureOpen(); - - // Make sure that a response has been recieved from remote - // before continuing - if (mPrivateInput == null || mReplyHeader.responseCode == -1) { - startProcessing(); - } - } - - /** - * Sends a request to the client of the specified type. - * This function will enable SRM and set SRM active if the server - * response allows this. - * @param opCode the request code to send to the client - * @return true if there is more data to send; - * false if there is no more data to send - * @throws IOException if an IO error occurs - */ - private boolean sendRequest(int opCode) throws IOException { - boolean returnValue = false; - ByteArrayOutputStream out = new ByteArrayOutputStream(); - int bodyLength = -1; - byte[] headerArray = ObexHelper.createHeader(mRequestHeader, true); - if (mPrivateOutput != null) { - bodyLength = mPrivateOutput.size(); - } - - /* - * Determine if there is space to add a body request. At present - * this method checks to see if there is room for at least a 17 - * byte body header. This number needs to be at least 6 so that - * there is room for the header ID and length and the reply ID and - * length, but it is a waste of resources if we can't send much of - * the body. - */ - final int MINIMUM_BODY_LENGTH = 3; - if ((ObexHelper.BASE_PACKET_LENGTH + headerArray.length + MINIMUM_BODY_LENGTH) - > mMaxPacketSize) { - int end = 0; - int start = 0; - // split & send the headerArray in multiple packets. - - while (end != headerArray.length) { - //split the headerArray - - end = ObexHelper.findHeaderEnd(headerArray, start, mMaxPacketSize - - ObexHelper.BASE_PACKET_LENGTH); - // can not split - if (end == -1) { - mOperationDone = true; - abort(); - mExceptionMessage = "Header larger then can be sent in a packet"; - mInputOpen = false; - - if (mPrivateInput != null) { - mPrivateInput.close(); - } - - if (mPrivateOutput != null) { - mPrivateOutput.close(); - } - throw new IOException("OBEX Packet exceeds max packet size"); - } - - byte[] sendHeader = new byte[end - start]; - System.arraycopy(headerArray, start, sendHeader, 0, sendHeader.length); - if (!mParent.sendRequest(opCode, sendHeader, mReplyHeader, mPrivateInput, false)) { - return false; - } - - if (mReplyHeader.responseCode != ResponseCodes.OBEX_HTTP_CONTINUE) { - return false; - } - - start = end; - } - - // Enable SRM if it should be enabled - checkForSrm(); - - if (bodyLength > 0) { - return true; - } else { - return false; - } - } else { - /* All headers will fit into a single package */ - if(mSendBodyHeader == false) { - /* As we are not to send any body data, set the FINAL_BIT */ - opCode |= ObexHelper.OBEX_OPCODE_FINAL_BIT_MASK; - } - out.write(headerArray); - } - - if (bodyLength > 0) { - /* - * Determine if we can send the whole body or just part of - * the body. Remember that there is the 3 bytes for the - * response message and 3 bytes for the header ID and length - */ - if (bodyLength > (mMaxPacketSize - headerArray.length - 6)) { - returnValue = true; - - bodyLength = mMaxPacketSize - headerArray.length - 6; - } - - byte[] body = mPrivateOutput.readBytes(bodyLength); - - /* - * Since this is a put request if the final bit is set or - * the output stream is closed we need to send the 0x49 - * (End of Body) otherwise, we need to send 0x48 (Body) - */ - if ((mPrivateOutput.isClosed()) && (!returnValue) && (!mEndOfBodySent) - && ((opCode & ObexHelper.OBEX_OPCODE_FINAL_BIT_MASK) != 0)) { - out.write(HeaderSet.END_OF_BODY); - mEndOfBodySent = true; - } else { - out.write(HeaderSet.BODY); - } - - bodyLength += 3; - out.write((byte)(bodyLength >> 8)); - out.write((byte)bodyLength); - - if (body != null) { - out.write(body); - } - } - - if (mPrivateOutputOpen && bodyLength <= 0 && !mEndOfBodySent) { - // only 0x82 or 0x83 can send 0x49 - if ((opCode & ObexHelper.OBEX_OPCODE_FINAL_BIT_MASK) == 0) { - out.write(HeaderSet.BODY); - } else { - out.write(HeaderSet.END_OF_BODY); - mEndOfBodySent = true; - } - - bodyLength = 3; - out.write((byte)(bodyLength >> 8)); - out.write((byte)bodyLength); - } - - if (out.size() == 0) { - if (!mParent.sendRequest(opCode, null, mReplyHeader, mPrivateInput, mSrmActive)) { - return false; - } - // Enable SRM if it should be enabled - checkForSrm(); - return returnValue; - } - if ((out.size() > 0) - && (!mParent.sendRequest(opCode, out.toByteArray(), - mReplyHeader, mPrivateInput, mSrmActive))) { - return false; - } - // Enable SRM if it should be enabled - checkForSrm(); - - // send all of the output data in 0x48, - // send 0x49 with empty body - if ((mPrivateOutput != null) && (mPrivateOutput.size() > 0)) - returnValue = true; - - return returnValue; - } - - private void checkForSrm() throws IOException { - Byte srmMode = (Byte)mReplyHeader.getHeader(HeaderSet.SINGLE_RESPONSE_MODE); - if(mParent.isSrmSupported() == true && srmMode != null - && srmMode == ObexHelper.OBEX_SRM_ENABLE) { - mSrmEnabled = true; - } - /** - * Call this only when a complete obex packet have been received. - * (This is not optimal, but the current design is not really suited to - * the way SRM is specified.) - * The BT usage of SRM is not really safe - it assumes that the SRMP will fit - * into every OBEX packet, hence if another header occupies the entire packet, - * the scheme will not work - unlikely though. - */ - if(mSrmEnabled) { - mSrmWaitingForRemote = false; - Byte srmp = (Byte)mReplyHeader.getHeader(HeaderSet.SINGLE_RESPONSE_MODE_PARAMETER); - if(srmp != null && srmp == ObexHelper.OBEX_SRMP_WAIT) { - mSrmWaitingForRemote = true; - // Clear the wait header, as the absence of the header in the next packet - // indicates don't wait anymore. - mReplyHeader.setHeader(HeaderSet.SINGLE_RESPONSE_MODE_PARAMETER, null); - } - } - if((mSrmWaitingForRemote == false) && (mSrmEnabled == true)) { - mSrmActive = true; - } - } - - /** - * This method starts the processing thread results. It will send the - * initial request. If the response takes more then one packet, a thread - * will be started to handle additional requests - * @throws IOException if an IO error occurs - */ - private synchronized void startProcessing() throws IOException { - - if (mPrivateInput == null) { - mPrivateInput = new PrivateInputStream(this); - } - boolean more = true; - - if (mGetOperation) { - if (!mOperationDone) { - if (!mGetFinalFlag) { - mReplyHeader.responseCode = ResponseCodes.OBEX_HTTP_CONTINUE; - while ((more) && (mReplyHeader.responseCode == - ResponseCodes.OBEX_HTTP_CONTINUE)) { - more = sendRequest(ObexHelper.OBEX_OPCODE_GET); - } - // For GET we need to loop until all headers have been sent, - // And then we wait for the first continue package with the - // reply. - if (mReplyHeader.responseCode == ResponseCodes.OBEX_HTTP_CONTINUE) { - mParent.sendRequest(ObexHelper.OBEX_OPCODE_GET_FINAL, - null, mReplyHeader, mPrivateInput, mSrmActive); - } - if (mReplyHeader.responseCode != ResponseCodes.OBEX_HTTP_CONTINUE) { - mOperationDone = true; - } else { - checkForSrm(); - } - } else { - more = sendRequest(ObexHelper.OBEX_OPCODE_GET_FINAL); - - if (more) { - throw new IOException("FINAL_GET forced, data didn't fit into one packet"); - } - - mOperationDone = true; - } - } - } else { - // PUT operation - if (!mOperationDone) { - mReplyHeader.responseCode = ResponseCodes.OBEX_HTTP_CONTINUE; - while ((more) && (mReplyHeader.responseCode == ResponseCodes.OBEX_HTTP_CONTINUE)) { - more = sendRequest(ObexHelper.OBEX_OPCODE_PUT); - } - } - - if (mReplyHeader.responseCode == ResponseCodes.OBEX_HTTP_CONTINUE) { - mParent.sendRequest(ObexHelper.OBEX_OPCODE_PUT_FINAL, - null, mReplyHeader, mPrivateInput, mSrmActive); - } - - if (mReplyHeader.responseCode != ResponseCodes.OBEX_HTTP_CONTINUE) { - mOperationDone = true; - } - } - } - - /** - * Continues the operation since there is no data to read. - * @param sendEmpty true if the operation should send an empty - * packet or not send anything if there is no data to send - * @param inStream true if the stream is input stream or is - * output stream - * @throws IOException if an IO error occurs - */ - public synchronized boolean continueOperation(boolean sendEmpty, boolean inStream) - throws IOException { - - // One path to the first put operation - the other one does not need to - // handle SRM, as all will fit into one packet. - - if (mGetOperation) { - if ((inStream) && (!mOperationDone)) { - // to deal with inputstream in get operation - mParent.sendRequest(ObexHelper.OBEX_OPCODE_GET_FINAL, - null, mReplyHeader, mPrivateInput, mSrmActive); - /* - * Determine if that was not the last packet in the operation - */ - if (mReplyHeader.responseCode != ResponseCodes.OBEX_HTTP_CONTINUE) { - mOperationDone = true; - } else { - checkForSrm(); - } - - return true; - - } else if ((!inStream) && (!mOperationDone)) { - // to deal with outputstream in get operation - - if (mPrivateInput == null) { - mPrivateInput = new PrivateInputStream(this); - } - - if (!mGetFinalFlag) { - sendRequest(ObexHelper.OBEX_OPCODE_GET); - } else { - sendRequest(ObexHelper.OBEX_OPCODE_GET_FINAL); - } - if (mReplyHeader.responseCode != ResponseCodes.OBEX_HTTP_CONTINUE) { - mOperationDone = true; - } - return true; - - } else if (mOperationDone) { - return false; - } - - } else { - // PUT operation - if ((!inStream) && (!mOperationDone)) { - // to deal with outputstream in put operation - if (mReplyHeader.responseCode == -1) { - mReplyHeader.responseCode = ResponseCodes.OBEX_HTTP_CONTINUE; - } - sendRequest(ObexHelper.OBEX_OPCODE_PUT); - return true; - } else if ((inStream) && (!mOperationDone)) { - // How to deal with inputstream in put operation ? - return false; - - } else if (mOperationDone) { - return false; - } - - } - return false; - } - - /** - * Called when the output or input stream is closed. - * @param inStream true if the input stream is closed; - * false if the output stream is closed - * @throws IOException if an IO error occurs - */ - public void streamClosed(boolean inStream) throws IOException { - if (!mGetOperation) { - if ((!inStream) && (!mOperationDone)) { - // to deal with outputstream in put operation - - boolean more = true; - - if ((mPrivateOutput != null) && (mPrivateOutput.size() <= 0)) { - byte[] headerArray = ObexHelper.createHeader(mRequestHeader, false); - if (headerArray.length <= 0) - more = false; - } - // If have not sent any data so send all now - if (mReplyHeader.responseCode == -1) { - mReplyHeader.responseCode = ResponseCodes.OBEX_HTTP_CONTINUE; - } - - while ((more) && (mReplyHeader.responseCode == ResponseCodes.OBEX_HTTP_CONTINUE)) { - more = sendRequest(ObexHelper.OBEX_OPCODE_PUT); - } - - /* - * According to the IrOBEX specification, after the final put, you - * only have a single reply to send. so we don't need the while - * loop. - */ - while (mReplyHeader.responseCode == ResponseCodes.OBEX_HTTP_CONTINUE) { - - sendRequest(ObexHelper.OBEX_OPCODE_PUT_FINAL); - } - mOperationDone = true; - } else if ((inStream) && (mOperationDone)) { - // how to deal with input stream in put stream ? - mOperationDone = true; - } - } else { - if ((inStream) && (!mOperationDone)) { - - // to deal with inputstream in get operation - // Have not sent any data so send it all now - - if (mReplyHeader.responseCode == -1) { - mReplyHeader.responseCode = ResponseCodes.OBEX_HTTP_CONTINUE; - } - - while (mReplyHeader.responseCode == ResponseCodes.OBEX_HTTP_CONTINUE && !mOperationDone) { - if (!sendRequest(ObexHelper.OBEX_OPCODE_GET_FINAL)) { - break; - } - } - while (mReplyHeader.responseCode == ResponseCodes.OBEX_HTTP_CONTINUE && !mOperationDone) { - mParent.sendRequest(ObexHelper.OBEX_OPCODE_GET_FINAL, null, - mReplyHeader, mPrivateInput, false); - // Regardless of the SRM state, wait for the response. - } - mOperationDone = true; - } else if ((!inStream) && (!mOperationDone)) { - // to deal with outputstream in get operation - // part of the data may have been sent in continueOperation. - - boolean more = true; - - if ((mPrivateOutput != null) && (mPrivateOutput.size() <= 0)) { - byte[] headerArray = ObexHelper.createHeader(mRequestHeader, false); - if (headerArray.length <= 0) - more = false; - } - - if (mPrivateInput == null) { - mPrivateInput = new PrivateInputStream(this); - } - if ((mPrivateOutput != null) && (mPrivateOutput.size() <= 0)) - more = false; - - mReplyHeader.responseCode = ResponseCodes.OBEX_HTTP_CONTINUE; - while ((more) && (mReplyHeader.responseCode == ResponseCodes.OBEX_HTTP_CONTINUE)) { - more = sendRequest(ObexHelper.OBEX_OPCODE_GET); - } - sendRequest(ObexHelper.OBEX_OPCODE_GET_FINAL); - // parent.sendRequest(0x83, null, replyHeaders, privateInput); - if (mReplyHeader.responseCode != ResponseCodes.OBEX_HTTP_CONTINUE) { - mOperationDone = true; - } - } - } - } - - public void noBodyHeader(){ - mSendBodyHeader = false; - } -} diff --git a/obex/javax/obex/ClientSession.java b/obex/javax/obex/ClientSession.java deleted file mode 100644 index 272a920754f5..000000000000 --- a/obex/javax/obex/ClientSession.java +++ /dev/null @@ -1,616 +0,0 @@ -/* - * Copyright (c) 2015 The Android Open Source Project - * Copyright (C) 2015 Samsung LSI - * Copyright (c) 2008-2009, Motorola, Inc. - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * - Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * - Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * - Neither the name of the Motorola, Inc. nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -package javax.obex; - -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; - -import android.util.Log; - -/** - * This class in an implementation of the OBEX ClientSession. - * @hide - */ -public final class ClientSession extends ObexSession { - - private static final String TAG = "ClientSession"; - - private boolean mOpen; - - // Determines if an OBEX layer connection has been established - private boolean mObexConnected; - - private byte[] mConnectionId = null; - - /* - * The max Packet size must be at least 255 according to the OBEX - * specification. - */ - private int mMaxTxPacketSize = ObexHelper.LOWER_LIMIT_MAX_PACKET_SIZE; - - private boolean mRequestActive; - - private final InputStream mInput; - - private final OutputStream mOutput; - - private final boolean mLocalSrmSupported; - - private final ObexTransport mTransport; - - public ClientSession(final ObexTransport trans) throws IOException { - mInput = trans.openInputStream(); - mOutput = trans.openOutputStream(); - mOpen = true; - mRequestActive = false; - mLocalSrmSupported = trans.isSrmSupported(); - mTransport = trans; - } - - /** - * Create a ClientSession - * @param trans The transport to use for OBEX transactions - * @param supportsSrm True if Single Response Mode should be used e.g. if the - * supplied transport is a TCP or l2cap channel. - * @throws IOException if it occurs while opening the transport streams. - */ - public ClientSession(final ObexTransport trans, final boolean supportsSrm) throws IOException { - mInput = trans.openInputStream(); - mOutput = trans.openOutputStream(); - mOpen = true; - mRequestActive = false; - mLocalSrmSupported = supportsSrm; - mTransport = trans; - } - - public HeaderSet connect(final HeaderSet header) throws IOException { - ensureOpen(); - if (mObexConnected) { - throw new IOException("Already connected to server"); - } - setRequestActive(); - - int totalLength = 4; - byte[] head = null; - - // Determine the header byte array - if (header != null) { - if (header.nonce != null) { - mChallengeDigest = new byte[16]; - System.arraycopy(header.nonce, 0, mChallengeDigest, 0, 16); - } - head = ObexHelper.createHeader(header, false); - totalLength += head.length; - } - /* - * Write the OBEX CONNECT packet to the server. - * Byte 0: 0x80 - * Byte 1&2: Connect Packet Length - * Byte 3: OBEX Version Number (Presently, 0x10) - * Byte 4: Flags (For TCP 0x00) - * Byte 5&6: Max OBEX Packet Length (Defined in MAX_PACKET_SIZE) - * Byte 7 to n: headers - */ - byte[] requestPacket = new byte[totalLength]; - int maxRxPacketSize = ObexHelper.getMaxRxPacketSize(mTransport); - // We just need to start at byte 3 since the sendRequest() method will - // handle the length and 0x80. - requestPacket[0] = (byte)0x10; - requestPacket[1] = (byte)0x00; - requestPacket[2] = (byte)(maxRxPacketSize >> 8); - requestPacket[3] = (byte)(maxRxPacketSize & 0xFF); - if (head != null) { - System.arraycopy(head, 0, requestPacket, 4, head.length); - } - - // Since we are not yet connected, the peer max packet size is unknown, - // hence we are only guaranteed the server will use the first 7 bytes. - if ((requestPacket.length + 3) > ObexHelper.MAX_PACKET_SIZE_INT) { - throw new IOException("Packet size exceeds max packet size for connect"); - } - - HeaderSet returnHeaderSet = new HeaderSet(); - sendRequest(ObexHelper.OBEX_OPCODE_CONNECT, requestPacket, returnHeaderSet, null, false); - - /* - * Read the response from the OBEX server. - * Byte 0: Response Code (If successful then OBEX_HTTP_OK) - * Byte 1&2: Packet Length - * Byte 3: OBEX Version Number - * Byte 4: Flags3 - * Byte 5&6: Max OBEX packet Length - * Byte 7 to n: Optional HeaderSet - */ - if (returnHeaderSet.responseCode == ResponseCodes.OBEX_HTTP_OK) { - mObexConnected = true; - } - setRequestInactive(); - - return returnHeaderSet; - } - - public Operation get(HeaderSet header) throws IOException { - - if (!mObexConnected) { - throw new IOException("Not connected to the server"); - } - setRequestActive(); - - ensureOpen(); - - HeaderSet head; - if (header == null) { - head = new HeaderSet(); - } else { - head = header; - if (head.nonce != null) { - mChallengeDigest = new byte[16]; - System.arraycopy(head.nonce, 0, mChallengeDigest, 0, 16); - } - } - // Add the connection ID if one exists - if (mConnectionId != null) { - head.mConnectionID = new byte[4]; - System.arraycopy(mConnectionId, 0, head.mConnectionID, 0, 4); - } - - if(mLocalSrmSupported) { - head.setHeader(HeaderSet.SINGLE_RESPONSE_MODE, ObexHelper.OBEX_SRM_ENABLE); - /* TODO: Consider creating an interface to get the wait state. - * On an android system, I cannot see when this is to be used. - * except perhaps if we are to wait for user accept on a push message. - if(getLocalWaitState()) { - head.setHeader(HeaderSet.SINGLE_RESPONSE_MODE_PARAMETER, ObexHelper.OBEX_SRMP_WAIT); - } - */ - } - - return new ClientOperation(mMaxTxPacketSize, this, head, true); - } - - /** - * 0xCB Connection Id an identifier used for OBEX connection multiplexing - */ - public void setConnectionID(long id) { - if ((id < 0) || (id > 0xFFFFFFFFL)) { - throw new IllegalArgumentException("Connection ID is not in a valid range"); - } - mConnectionId = ObexHelper.convertToByteArray(id); - } - - public HeaderSet delete(HeaderSet header) throws IOException { - - Operation op = put(header); - op.getResponseCode(); - HeaderSet returnValue = op.getReceivedHeader(); - op.close(); - - return returnValue; - } - - public HeaderSet disconnect(HeaderSet header) throws IOException { - if (!mObexConnected) { - throw new IOException("Not connected to the server"); - } - setRequestActive(); - - ensureOpen(); - // Determine the header byte array - byte[] head = null; - if (header != null) { - if (header.nonce != null) { - mChallengeDigest = new byte[16]; - System.arraycopy(header.nonce, 0, mChallengeDigest, 0, 16); - } - // Add the connection ID if one exists - if (mConnectionId != null) { - header.mConnectionID = new byte[4]; - System.arraycopy(mConnectionId, 0, header.mConnectionID, 0, 4); - } - head = ObexHelper.createHeader(header, false); - - if ((head.length + 3) > mMaxTxPacketSize) { - throw new IOException("Packet size exceeds max packet size"); - } - } else { - // Add the connection ID if one exists - if (mConnectionId != null) { - head = new byte[5]; - head[0] = (byte)HeaderSet.CONNECTION_ID; - System.arraycopy(mConnectionId, 0, head, 1, 4); - } - } - - HeaderSet returnHeaderSet = new HeaderSet(); - sendRequest(ObexHelper.OBEX_OPCODE_DISCONNECT, head, returnHeaderSet, null, false); - - /* - * An OBEX DISCONNECT reply from the server: - * Byte 1: Response code - * Bytes 2 & 3: packet size - * Bytes 4 & up: headers - */ - - /* response code , and header are ignored - * */ - - synchronized (this) { - mObexConnected = false; - setRequestInactive(); - } - - return returnHeaderSet; - } - - public long getConnectionID() { - - if (mConnectionId == null) { - return -1; - } - return ObexHelper.convertToLong(mConnectionId); - } - - public Operation put(HeaderSet header) throws IOException { - if (!mObexConnected) { - throw new IOException("Not connected to the server"); - } - setRequestActive(); - - ensureOpen(); - HeaderSet head; - if (header == null) { - head = new HeaderSet(); - } else { - head = header; - // when auth is initiated by client ,save the digest - if (head.nonce != null) { - mChallengeDigest = new byte[16]; - System.arraycopy(head.nonce, 0, mChallengeDigest, 0, 16); - } - } - - // Add the connection ID if one exists - if (mConnectionId != null) { - - head.mConnectionID = new byte[4]; - System.arraycopy(mConnectionId, 0, head.mConnectionID, 0, 4); - } - - if(mLocalSrmSupported) { - head.setHeader(HeaderSet.SINGLE_RESPONSE_MODE, ObexHelper.OBEX_SRM_ENABLE); - /* TODO: Consider creating an interface to get the wait state. - * On an android system, I cannot see when this is to be used. - if(getLocalWaitState()) { - head.setHeader(HeaderSet.SINGLE_RESPONSE_MODE_PARAMETER, ObexHelper.OBEX_SRMP_WAIT); - } - */ - } - return new ClientOperation(mMaxTxPacketSize, this, head, false); - } - - public void setAuthenticator(Authenticator auth) throws IOException { - if (auth == null) { - throw new IOException("Authenticator may not be null"); - } - mAuthenticator = auth; - } - - public HeaderSet setPath(HeaderSet header, boolean backup, boolean create) throws IOException { - if (!mObexConnected) { - throw new IOException("Not connected to the server"); - } - setRequestActive(); - ensureOpen(); - - int totalLength = 2; - byte[] head = null; - HeaderSet headset; - if (header == null) { - headset = new HeaderSet(); - } else { - headset = header; - if (headset.nonce != null) { - mChallengeDigest = new byte[16]; - System.arraycopy(headset.nonce, 0, mChallengeDigest, 0, 16); - } - } - - // when auth is initiated by client ,save the digest - if (headset.nonce != null) { - mChallengeDigest = new byte[16]; - System.arraycopy(headset.nonce, 0, mChallengeDigest, 0, 16); - } - - // Add the connection ID if one exists - if (mConnectionId != null) { - headset.mConnectionID = new byte[4]; - System.arraycopy(mConnectionId, 0, headset.mConnectionID, 0, 4); - } - - head = ObexHelper.createHeader(headset, false); - totalLength += head.length; - - if (totalLength > mMaxTxPacketSize) { - throw new IOException("Packet size exceeds max packet size"); - } - - int flags = 0; - /* - * The backup flag bit is bit 0 so if we add 1, this will set that bit - */ - if (backup) { - flags++; - } - /* - * The create bit is bit 1 so if we or with 2 the bit will be set. - */ - if (!create) { - flags |= 2; - } - - /* - * An OBEX SETPATH packet to the server: - * Byte 1: 0x85 - * Byte 2 & 3: packet size - * Byte 4: flags - * Byte 5: constants - * Byte 6 & up: headers - */ - byte[] packet = new byte[totalLength]; - packet[0] = (byte)flags; - packet[1] = (byte)0x00; - if (headset != null) { - System.arraycopy(head, 0, packet, 2, head.length); - } - - HeaderSet returnHeaderSet = new HeaderSet(); - sendRequest(ObexHelper.OBEX_OPCODE_SETPATH, packet, returnHeaderSet, null, false); - - /* - * An OBEX SETPATH reply from the server: - * Byte 1: Response code - * Bytes 2 & 3: packet size - * Bytes 4 & up: headers - */ - - setRequestInactive(); - - return returnHeaderSet; - } - - /** - * Verifies that the connection is open. - * @throws IOException if the connection is closed - */ - public synchronized void ensureOpen() throws IOException { - if (!mOpen) { - throw new IOException("Connection closed"); - } - } - - /** - * Set request inactive. Allows Put and get operation objects to tell this - * object when they are done. - */ - /*package*/synchronized void setRequestInactive() { - mRequestActive = false; - } - - /** - * Set request to active. - * @throws IOException if already active - */ - private synchronized void setRequestActive() throws IOException { - if (mRequestActive) { - throw new IOException("OBEX request is already being performed"); - } - mRequestActive = true; - } - - /** - * Sends a standard request to the client. It will then wait for the reply - * and update the header set object provided. If any authentication headers - * (i.e. authentication challenge or authentication response) are received, - * they will be processed. - * @param opCode the type of request to send to the client - * @param head the headers to send to the client - * @param header the header object to update with the response - * @param privateInput the input stream used by the Operation object; null - * if this is called on a CONNECT, SETPATH or DISCONNECT - * @return - * true if the operation completed successfully; - * false if an authentication response failed to pass - * @throws IOException if an IO error occurs - */ - public boolean sendRequest(int opCode, byte[] head, HeaderSet header, - PrivateInputStream privateInput, boolean srmActive) throws IOException { - //check header length with local max size - if (head != null) { - if ((head.length + 3) > ObexHelper.MAX_PACKET_SIZE_INT) { - // TODO: This is an implementation limit - not a specification requirement. - throw new IOException("header too large "); - } - } - - boolean skipSend = false; - boolean skipReceive = false; - if (srmActive == true) { - if (opCode == ObexHelper.OBEX_OPCODE_PUT) { - // we are in the middle of a SRM PUT operation, don't expect a continue. - skipReceive = true; - } else if (opCode == ObexHelper.OBEX_OPCODE_GET) { - // We are still sending the get request, send, but don't expect continue - // until the request is transfered (the final bit is set) - skipReceive = true; - } else if (opCode == ObexHelper.OBEX_OPCODE_GET_FINAL) { - // All done sending the request, expect data from the server, without - // sending continue. - skipSend = true; - } - - } - - int bytesReceived; - ByteArrayOutputStream out = new ByteArrayOutputStream(); - out.write((byte)opCode); - - // Determine if there are any headers to send - if (head == null) { - out.write(0x00); - out.write(0x03); - } else { - out.write((byte)((head.length + 3) >> 8)); - out.write((byte)(head.length + 3)); - out.write(head); - } - - if (!skipSend) { - // Write the request to the output stream and flush the stream - mOutput.write(out.toByteArray()); - // TODO: is this really needed? if this flush is implemented - // correctly, we will get a gap between each obex packet. - // which is kind of the idea behind SRM to avoid. - // Consider offloading to another thread (async action) - mOutput.flush(); - } - - if (!skipReceive) { - header.responseCode = mInput.read(); - - int length = ((mInput.read() << 8) | (mInput.read())); - - if (length > ObexHelper.getMaxRxPacketSize(mTransport)) { - throw new IOException("Packet received exceeds packet size limit"); - } - if (length > ObexHelper.BASE_PACKET_LENGTH) { - byte[] data = null; - if (opCode == ObexHelper.OBEX_OPCODE_CONNECT) { - @SuppressWarnings("unused") - int version = mInput.read(); - @SuppressWarnings("unused") - int flags = mInput.read(); - mMaxTxPacketSize = (mInput.read() << 8) + mInput.read(); - - //check with local max size - if (mMaxTxPacketSize > ObexHelper.MAX_CLIENT_PACKET_SIZE) { - mMaxTxPacketSize = ObexHelper.MAX_CLIENT_PACKET_SIZE; - } - - // check with transport maximum size - if(mMaxTxPacketSize > ObexHelper.getMaxTxPacketSize(mTransport)) { - // To increase this size, increase the buffer size in L2CAP layer - // in Bluedroid. - Log.w(TAG, "An OBEX packet size of " + mMaxTxPacketSize + "was" - + " requested. Transport only allows: " - + ObexHelper.getMaxTxPacketSize(mTransport) - + " Lowering limit to this value."); - mMaxTxPacketSize = ObexHelper.getMaxTxPacketSize(mTransport); - } - - if (length > 7) { - data = new byte[length - 7]; - - bytesReceived = mInput.read(data); - while (bytesReceived != (length - 7)) { - bytesReceived += mInput.read(data, bytesReceived, data.length - - bytesReceived); - } - } else { - return true; - } - } else { - data = new byte[length - 3]; - bytesReceived = mInput.read(data); - - while (bytesReceived != (length - 3)) { - bytesReceived += mInput.read(data, bytesReceived, data.length - bytesReceived); - } - if (opCode == ObexHelper.OBEX_OPCODE_ABORT) { - return true; - } - } - - byte[] body = ObexHelper.updateHeaderSet(header, data); - if ((privateInput != null) && (body != null)) { - privateInput.writeBytes(body, 1); - } - - if (header.mConnectionID != null) { - mConnectionId = new byte[4]; - System.arraycopy(header.mConnectionID, 0, mConnectionId, 0, 4); - } - - if (header.mAuthResp != null) { - if (!handleAuthResp(header.mAuthResp)) { - setRequestInactive(); - throw new IOException("Authentication Failed"); - } - } - - if ((header.responseCode == ResponseCodes.OBEX_HTTP_UNAUTHORIZED) - && (header.mAuthChall != null)) { - - if (handleAuthChall(header)) { - out.write((byte)HeaderSet.AUTH_RESPONSE); - out.write((byte)((header.mAuthResp.length + 3) >> 8)); - out.write((byte)(header.mAuthResp.length + 3)); - out.write(header.mAuthResp); - header.mAuthChall = null; - header.mAuthResp = null; - - byte[] sendHeaders = new byte[out.size() - 3]; - System.arraycopy(out.toByteArray(), 3, sendHeaders, 0, sendHeaders.length); - - return sendRequest(opCode, sendHeaders, header, privateInput, false); - } - } - } - } - - return true; - } - - public void close() throws IOException { - mOpen = false; - mInput.close(); - mOutput.close(); - } - - public boolean isSrmSupported() { - return mLocalSrmSupported; - } -} diff --git a/obex/javax/obex/HeaderSet.java b/obex/javax/obex/HeaderSet.java deleted file mode 100644 index 35fe1863e1fb..000000000000 --- a/obex/javax/obex/HeaderSet.java +++ /dev/null @@ -1,710 +0,0 @@ -/* - * Copyright (c) 2014 The Android Open Source Project - * Copyright (c) 2008-2009, Motorola, Inc. - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * - Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * - Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * - Neither the name of the Motorola, Inc. nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -package javax.obex; - -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.util.Calendar; -import java.security.SecureRandom; - -/** - * This class implements the javax.obex.HeaderSet interface for OBEX over - * RFCOMM or OBEX over l2cap. - * @hide - */ -public final class HeaderSet { - - /** - * Represents the OBEX Count header. This allows the connection statement to - * tell the server how many objects it plans to send or retrieve. - *

- * The value of COUNT is 0xC0 (192). - */ - public static final int COUNT = 0xC0; - - /** - * Represents the OBEX Name header. This specifies the name of the object. - *

- * The value of NAME is 0x01 (1). - */ - public static final int NAME = 0x01; - - /** - * Represents the OBEX Type header. This allows a request to specify the - * type of the object (e.g. text, html, binary, etc.). - *

- * The value of TYPE is 0x42 (66). - */ - public static final int TYPE = 0x42; - - /** - * Represents the OBEX Length header. This is the length of the object in - * bytes. - *

- * The value of LENGTH is 0xC3 (195). - */ - public static final int LENGTH = 0xC3; - - /** - * Represents the OBEX Time header using the ISO 8601 standards. This is the - * preferred time header. - *

- * The value of TIME_ISO_8601 is 0x44 (68). - */ - public static final int TIME_ISO_8601 = 0x44; - - /** - * Represents the OBEX Time header using the 4 byte representation. This is - * only included for backwards compatibility. It represents the number of - * seconds since January 1, 1970. - *

- * The value of TIME_4_BYTE is 0xC4 (196). - */ - public static final int TIME_4_BYTE = 0xC4; - - /** - * Represents the OBEX Description header. This is a text description of the - * object. - *

- * The value of DESCRIPTION is 0x05 (5). - */ - public static final int DESCRIPTION = 0x05; - - /** - * Represents the OBEX Target header. This is the name of the service an - * operation is targeted to. - *

- * The value of TARGET is 0x46 (70). - */ - public static final int TARGET = 0x46; - - /** - * Represents the OBEX HTTP header. This allows an HTTP 1.X header to be - * included in a request or reply. - *

- * The value of HTTP is 0x47 (71). - */ - public static final int HTTP = 0x47; - - /** - * Represents the OBEX BODY header. - *

- * The value of BODY is 0x48 (72). - */ - public static final int BODY = 0x48; - - /** - * Represents the OBEX End of BODY header. - *

- * The value of BODY is 0x49 (73). - */ - public static final int END_OF_BODY = 0x49; - - /** - * Represents the OBEX Who header. Identifies the OBEX application to - * determine if the two peers are talking to each other. - *

- * The value of WHO is 0x4A (74). - */ - public static final int WHO = 0x4A; - - /** - * Represents the OBEX Connection ID header. Identifies used for OBEX - * connection multiplexing. - *

- * The value of CONNECTION_ID is 0xCB (203). - */ - - public static final int CONNECTION_ID = 0xCB; - - /** - * Represents the OBEX Application Parameter header. This header specifies - * additional application request and response information. - *

- * The value of APPLICATION_PARAMETER is 0x4C (76). - */ - public static final int APPLICATION_PARAMETER = 0x4C; - - /** - * Represents the OBEX authentication digest-challenge. - *

- * The value of AUTH_CHALLENGE is 0x4D (77). - */ - public static final int AUTH_CHALLENGE = 0x4D; - - /** - * Represents the OBEX authentication digest-response. - *

- * The value of AUTH_RESPONSE is 0x4E (78). - */ - public static final int AUTH_RESPONSE = 0x4E; - - /** - * Represents the OBEX Object Class header. This header specifies the OBEX - * object class of the object. - *

- * The value of OBJECT_CLASS is 0x4F (79). - */ - public static final int OBJECT_CLASS = 0x4F; - - /** - * Represents the OBEX Single Response Mode (SRM). This header is used - * for Single response mode, introduced in OBEX 1.5. - *

- * The value of SINGLE_RESPONSE_MODE is 0x97 (151). - */ - public static final int SINGLE_RESPONSE_MODE = 0x97; - - /** - * Represents the OBEX Single Response Mode Parameters. This header is used - * for Single response mode, introduced in OBEX 1.5. - *

- * The value of SINGLE_RESPONSE_MODE_PARAMETER is 0x98 (152). - */ - public static final int SINGLE_RESPONSE_MODE_PARAMETER = 0x98; - - private Long mCount; // 4 byte unsigned integer - - private String mName; // null terminated Unicode text string - - private boolean mEmptyName; - - private String mType; // null terminated ASCII text string - - private Long mLength; // 4 byte unsigend integer - - private Calendar mIsoTime; // String of the form YYYYMMDDTHHMMSSZ - - private Calendar mByteTime; // 4 byte unsigned integer - - private String mDescription; // null terminated Unicode text String - - private byte[] mTarget; // byte sequence - - private byte[] mHttpHeader; // byte sequence - - private byte[] mWho; // length prefixed byte sequence - - private byte[] mAppParam; // byte sequence of the form tag length value - - private byte[] mObjectClass; // byte sequence - - private String[] mUnicodeUserDefined; // null terminated unicode string - - private byte[][] mSequenceUserDefined; // byte sequence user defined - - private Byte[] mByteUserDefined; // 1 byte - - private Long[] mIntegerUserDefined; // 4 byte unsigned integer - - private SecureRandom mRandom = null; - - private Byte mSingleResponseMode; // byte to indicate enable/disable/support for SRM - - private Byte mSrmParam; // byte representing the SRM parameters - only "wait" - // is supported by Bluetooth - - /*package*/ byte[] nonce; - - public byte[] mAuthChall; // The authentication challenge header - - public byte[] mAuthResp; // The authentication response header - - public byte[] mConnectionID; // THe connection ID - - public int responseCode; - - /** - * Creates new HeaderSet object. - * @param size the max packet size for this connection - */ - public HeaderSet() { - mUnicodeUserDefined = new String[16]; - mSequenceUserDefined = new byte[16][]; - mByteUserDefined = new Byte[16]; - mIntegerUserDefined = new Long[16]; - responseCode = -1; - } - - /** - * Sets flag for special "value" of NAME header which should be empty. This - * is not the same as NAME header with empty string in which case it will - * have length of 5 bytes. It should be 3 bytes with only header id and - * length field. - */ - public void setEmptyNameHeader() { - mName = null; - mEmptyName = true; - } - - /** - * Gets flag for special "value" of NAME header which should be empty. See - * above. - */ - public boolean getEmptyNameHeader() { - return mEmptyName; - } - - /** - * Sets the value of the header identifier to the value provided. The type - * of object must correspond to the Java type defined in the description of - * this interface. If null is passed as the - * headerValue then the header will be removed from the set of - * headers to include in the next request. - * @param headerID the identifier to include in the message - * @param headerValue the value of the header identifier - * @throws IllegalArgumentException if the header identifier provided is not - * one defined in this interface or a user-defined header; if the - * type of headerValue is not the correct Java type as - * defined in the description of this interface\ - */ - public void setHeader(int headerID, Object headerValue) { - long temp = -1; - - switch (headerID) { - case COUNT: - if (!(headerValue instanceof Long)) { - if (headerValue == null) { - mCount = null; - break; - } - throw new IllegalArgumentException("Count must be a Long"); - } - temp = ((Long)headerValue).longValue(); - if ((temp < 0L) || (temp > 0xFFFFFFFFL)) { - throw new IllegalArgumentException("Count must be between 0 and 0xFFFFFFFF"); - } - mCount = (Long)headerValue; - break; - case NAME: - if ((headerValue != null) && (!(headerValue instanceof String))) { - throw new IllegalArgumentException("Name must be a String"); - } - mEmptyName = false; - mName = (String)headerValue; - break; - case TYPE: - if ((headerValue != null) && (!(headerValue instanceof String))) { - throw new IllegalArgumentException("Type must be a String"); - } - mType = (String)headerValue; - break; - case LENGTH: - if (!(headerValue instanceof Long)) { - if (headerValue == null) { - mLength = null; - break; - } - throw new IllegalArgumentException("Length must be a Long"); - } - temp = ((Long)headerValue).longValue(); - if ((temp < 0L) || (temp > 0xFFFFFFFFL)) { - throw new IllegalArgumentException("Length must be between 0 and 0xFFFFFFFF"); - } - mLength = (Long)headerValue; - break; - case TIME_ISO_8601: - if ((headerValue != null) && (!(headerValue instanceof Calendar))) { - throw new IllegalArgumentException("Time ISO 8601 must be a Calendar"); - } - mIsoTime = (Calendar)headerValue; - break; - case TIME_4_BYTE: - if ((headerValue != null) && (!(headerValue instanceof Calendar))) { - throw new IllegalArgumentException("Time 4 Byte must be a Calendar"); - } - mByteTime = (Calendar)headerValue; - break; - case DESCRIPTION: - if ((headerValue != null) && (!(headerValue instanceof String))) { - throw new IllegalArgumentException("Description must be a String"); - } - mDescription = (String)headerValue; - break; - case TARGET: - if (headerValue == null) { - mTarget = null; - } else { - if (!(headerValue instanceof byte[])) { - throw new IllegalArgumentException("Target must be a byte array"); - } else { - mTarget = new byte[((byte[])headerValue).length]; - System.arraycopy(headerValue, 0, mTarget, 0, mTarget.length); - } - } - break; - case HTTP: - if (headerValue == null) { - mHttpHeader = null; - } else { - if (!(headerValue instanceof byte[])) { - throw new IllegalArgumentException("HTTP must be a byte array"); - } else { - mHttpHeader = new byte[((byte[])headerValue).length]; - System.arraycopy(headerValue, 0, mHttpHeader, 0, mHttpHeader.length); - } - } - break; - case WHO: - if (headerValue == null) { - mWho = null; - } else { - if (!(headerValue instanceof byte[])) { - throw new IllegalArgumentException("WHO must be a byte array"); - } else { - mWho = new byte[((byte[])headerValue).length]; - System.arraycopy(headerValue, 0, mWho, 0, mWho.length); - } - } - break; - case OBJECT_CLASS: - if (headerValue == null) { - mObjectClass = null; - } else { - if (!(headerValue instanceof byte[])) { - throw new IllegalArgumentException("Object Class must be a byte array"); - } else { - mObjectClass = new byte[((byte[])headerValue).length]; - System.arraycopy(headerValue, 0, mObjectClass, 0, mObjectClass.length); - } - } - break; - case APPLICATION_PARAMETER: - if (headerValue == null) { - mAppParam = null; - } else { - if (!(headerValue instanceof byte[])) { - throw new IllegalArgumentException( - "Application Parameter must be a byte array"); - } else { - mAppParam = new byte[((byte[])headerValue).length]; - System.arraycopy(headerValue, 0, mAppParam, 0, mAppParam.length); - } - } - break; - case SINGLE_RESPONSE_MODE: - if (headerValue == null) { - mSingleResponseMode = null; - } else { - if (!(headerValue instanceof Byte)) { - throw new IllegalArgumentException( - "Single Response Mode must be a Byte"); - } else { - mSingleResponseMode = (Byte)headerValue; - } - } - break; - case SINGLE_RESPONSE_MODE_PARAMETER: - if (headerValue == null) { - mSrmParam = null; - } else { - if (!(headerValue instanceof Byte)) { - throw new IllegalArgumentException( - "Single Response Mode Parameter must be a Byte"); - } else { - mSrmParam = (Byte)headerValue; - } - } - break; - default: - // Verify that it was not a Unicode String user Defined - if ((headerID >= 0x30) && (headerID <= 0x3F)) { - if ((headerValue != null) && (!(headerValue instanceof String))) { - throw new IllegalArgumentException( - "Unicode String User Defined must be a String"); - } - mUnicodeUserDefined[headerID - 0x30] = (String)headerValue; - - break; - } - // Verify that it was not a byte sequence user defined value - if ((headerID >= 0x70) && (headerID <= 0x7F)) { - - if (headerValue == null) { - mSequenceUserDefined[headerID - 0x70] = null; - } else { - if (!(headerValue instanceof byte[])) { - throw new IllegalArgumentException( - "Byte Sequence User Defined must be a byte array"); - } else { - mSequenceUserDefined[headerID - 0x70] = new byte[((byte[])headerValue).length]; - System.arraycopy(headerValue, 0, mSequenceUserDefined[headerID - 0x70], - 0, mSequenceUserDefined[headerID - 0x70].length); - } - } - break; - } - // Verify that it was not a Byte user Defined - if ((headerID >= 0xB0) && (headerID <= 0xBF)) { - if ((headerValue != null) && (!(headerValue instanceof Byte))) { - throw new IllegalArgumentException("ByteUser Defined must be a Byte"); - } - mByteUserDefined[headerID - 0xB0] = (Byte)headerValue; - - break; - } - // Verify that is was not the 4 byte unsigned integer user - // defined header - if ((headerID >= 0xF0) && (headerID <= 0xFF)) { - if (!(headerValue instanceof Long)) { - if (headerValue == null) { - mIntegerUserDefined[headerID - 0xF0] = null; - break; - } - throw new IllegalArgumentException("Integer User Defined must be a Long"); - } - temp = ((Long)headerValue).longValue(); - if ((temp < 0L) || (temp > 0xFFFFFFFFL)) { - throw new IllegalArgumentException( - "Integer User Defined must be between 0 and 0xFFFFFFFF"); - } - mIntegerUserDefined[headerID - 0xF0] = (Long)headerValue; - break; - } - throw new IllegalArgumentException("Invalid Header Identifier"); - } - } - - /** - * Retrieves the value of the header identifier provided. The type of the - * Object returned is defined in the description of this interface. - * @param headerID the header identifier whose value is to be returned - * @return the value of the header provided or null if the - * header identifier specified is not part of this - * HeaderSet object - * @throws IllegalArgumentException if the headerID is not one - * defined in this interface or any of the user-defined headers - * @throws IOException if an error occurred in the transport layer during - * the operation or if the connection has been closed - */ - public Object getHeader(int headerID) throws IOException { - - switch (headerID) { - case COUNT: - return mCount; - case NAME: - return mName; - case TYPE: - return mType; - case LENGTH: - return mLength; - case TIME_ISO_8601: - return mIsoTime; - case TIME_4_BYTE: - return mByteTime; - case DESCRIPTION: - return mDescription; - case TARGET: - return mTarget; - case HTTP: - return mHttpHeader; - case WHO: - return mWho; - case CONNECTION_ID: - return mConnectionID; - case OBJECT_CLASS: - return mObjectClass; - case APPLICATION_PARAMETER: - return mAppParam; - case SINGLE_RESPONSE_MODE: - return mSingleResponseMode; - case SINGLE_RESPONSE_MODE_PARAMETER: - return mSrmParam; - default: - // Verify that it was not a Unicode String user Defined - if ((headerID >= 0x30) && (headerID <= 0x3F)) { - return mUnicodeUserDefined[headerID - 0x30]; - } - // Verify that it was not a byte sequence user defined header - if ((headerID >= 0x70) && (headerID <= 0x7F)) { - return mSequenceUserDefined[headerID - 0x70]; - } - // Verify that it was not a byte user defined header - if ((headerID >= 0xB0) && (headerID <= 0xBF)) { - return mByteUserDefined[headerID - 0xB0]; - } - // Verify that it was not a integer user defined header - if ((headerID >= 0xF0) && (headerID <= 0xFF)) { - return mIntegerUserDefined[headerID - 0xF0]; - } - throw new IllegalArgumentException("Invalid Header Identifier"); - } - } - - /** - * Retrieves the list of headers that may be retrieved via the - * getHeader method that will not return null. In - * other words, this method returns all the headers that are available in - * this object. - * @see #getHeader - * @return the array of headers that are set in this object or - * null if no headers are available - * @throws IOException if an error occurred in the transport layer during - * the operation or the connection has been closed - */ - public int[] getHeaderList() throws IOException { - ByteArrayOutputStream out = new ByteArrayOutputStream(); - - if (mCount != null) { - out.write(COUNT); - } - if (mName != null) { - out.write(NAME); - } - if (mType != null) { - out.write(TYPE); - } - if (mLength != null) { - out.write(LENGTH); - } - if (mIsoTime != null) { - out.write(TIME_ISO_8601); - } - if (mByteTime != null) { - out.write(TIME_4_BYTE); - } - if (mDescription != null) { - out.write(DESCRIPTION); - } - if (mTarget != null) { - out.write(TARGET); - } - if (mHttpHeader != null) { - out.write(HTTP); - } - if (mWho != null) { - out.write(WHO); - } - if (mAppParam != null) { - out.write(APPLICATION_PARAMETER); - } - if (mObjectClass != null) { - out.write(OBJECT_CLASS); - } - if(mSingleResponseMode != null) { - out.write(SINGLE_RESPONSE_MODE); - } - if(mSrmParam != null) { - out.write(SINGLE_RESPONSE_MODE_PARAMETER); - } - - for (int i = 0x30; i < 0x40; i++) { - if (mUnicodeUserDefined[i - 0x30] != null) { - out.write(i); - } - } - - for (int i = 0x70; i < 0x80; i++) { - if (mSequenceUserDefined[i - 0x70] != null) { - out.write(i); - } - } - - for (int i = 0xB0; i < 0xC0; i++) { - if (mByteUserDefined[i - 0xB0] != null) { - out.write(i); - } - } - - for (int i = 0xF0; i < 0x100; i++) { - if (mIntegerUserDefined[i - 0xF0] != null) { - out.write(i); - } - } - - byte[] headers = out.toByteArray(); - out.close(); - - if ((headers == null) || (headers.length == 0)) { - return null; - } - - int[] result = new int[headers.length]; - for (int i = 0; i < headers.length; i++) { - // Convert the byte to a positive integer. That is, an integer - // between 0 and 256. - result[i] = headers[i] & 0xFF; - } - - return result; - } - - /** - * Sets the authentication challenge header. The realm will be - * encoded based upon the default encoding scheme used by the implementation - * to encode strings. Therefore, the encoding scheme used to encode the - * realm is application dependent. - * @param realm a short description that describes what password to use; if - * null no realm will be sent in the authentication - * challenge header - * @param userID if true, a user ID is required in the reply; - * if false, no user ID is required - * @param access if true then full access will be granted if - * successful; if false then read-only access will be - * granted if successful - * @throws IOException - */ - public void createAuthenticationChallenge(String realm, boolean userID, boolean access) - throws IOException { - - nonce = new byte[16]; - if(mRandom == null) { - mRandom = new SecureRandom(); - } - for (int i = 0; i < 16; i++) { - nonce[i] = (byte)mRandom.nextInt(); - } - - mAuthChall = ObexHelper.computeAuthenticationChallenge(nonce, realm, access, userID); - } - - /** - * Returns the response code received from the server. Response codes are - * defined in the ResponseCodes class. - * @see ResponseCodes - * @return the response code retrieved from the server - * @throws IOException if an error occurred in the transport layer during - * the transaction; if this method is called on a - * HeaderSet object created by calling - * createHeaderSet() in a ClientSession - * object; if this object was created by an OBEX server - */ - public int getResponseCode() throws IOException { - if (responseCode == -1) { - throw new IOException("May not be called on a server"); - } else { - return responseCode; - } - } -} diff --git a/obex/javax/obex/ObexHelper.java b/obex/javax/obex/ObexHelper.java deleted file mode 100644 index 843793ad98f8..000000000000 --- a/obex/javax/obex/ObexHelper.java +++ /dev/null @@ -1,1100 +0,0 @@ -/* - * Copyright (C) 2015 The Android Open Source Project - * Copyright (C) 2015 Samsung LSI - * Copyright (c) 2008-2009, Motorola, Inc. - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * - Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * - Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * - Neither the name of the Motorola, Inc. nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -package javax.obex; - -import android.util.Log; - -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.UnsupportedEncodingException; -import java.security.MessageDigest; -import java.security.NoSuchAlgorithmException; -import java.util.Calendar; -import java.util.Date; -import java.util.TimeZone; - - -/** - * This class defines a set of helper methods for the implementation of Obex. - * @hide - */ -public final class ObexHelper { - - private static final String TAG = "ObexHelper"; - public static final boolean VDBG = false; - /** - * Defines the basic packet length used by OBEX. Every OBEX packet has the - * same basic format:
- * Byte 0: Request or Response Code Byte 1&2: Length of the packet. - */ - public static final int BASE_PACKET_LENGTH = 3; - - /** Prevent object construction of helper class */ - private ObexHelper() { - } - - /** - * The maximum packet size for OBEX packets that this client can handle. At - * present, this must be changed for each port. TODO: The max packet size - * should be the Max incoming MTU minus TODO: L2CAP package headers and - * RFCOMM package headers. TODO: Retrieve the max incoming MTU from TODO: - * LocalDevice.getProperty(). - * NOTE: This value must be larger than or equal to the L2CAP SDU - */ - /* - * android note set as 0xFFFE to match remote MPS - */ - public static final int MAX_PACKET_SIZE_INT = 0xFFFE; - - // The minimum allowed max packet size is 255 according to the OBEX specification - public static final int LOWER_LIMIT_MAX_PACKET_SIZE = 255; - - // The length of OBEX Byte Sequency Header Id according to the OBEX specification - public static final int OBEX_BYTE_SEQ_HEADER_LEN = 0x03; - - /** - * Temporary workaround to be able to push files to Windows 7. - * TODO: Should be removed as soon as Microsoft updates their driver. - */ - public static final int MAX_CLIENT_PACKET_SIZE = 0xFC00; - - public static final int OBEX_OPCODE_FINAL_BIT_MASK = 0x80; - - public static final int OBEX_OPCODE_CONNECT = 0x80; - - public static final int OBEX_OPCODE_DISCONNECT = 0x81; - - public static final int OBEX_OPCODE_PUT = 0x02; - - public static final int OBEX_OPCODE_PUT_FINAL = 0x82; - - public static final int OBEX_OPCODE_GET = 0x03; - - public static final int OBEX_OPCODE_GET_FINAL = 0x83; - - public static final int OBEX_OPCODE_RESERVED = 0x04; - - public static final int OBEX_OPCODE_RESERVED_FINAL = 0x84; - - public static final int OBEX_OPCODE_SETPATH = 0x85; - - public static final int OBEX_OPCODE_ABORT = 0xFF; - - public static final int OBEX_AUTH_REALM_CHARSET_ASCII = 0x00; - - public static final int OBEX_AUTH_REALM_CHARSET_ISO_8859_1 = 0x01; - - public static final int OBEX_AUTH_REALM_CHARSET_ISO_8859_2 = 0x02; - - public static final int OBEX_AUTH_REALM_CHARSET_ISO_8859_3 = 0x03; - - public static final int OBEX_AUTH_REALM_CHARSET_ISO_8859_4 = 0x04; - - public static final int OBEX_AUTH_REALM_CHARSET_ISO_8859_5 = 0x05; - - public static final int OBEX_AUTH_REALM_CHARSET_ISO_8859_6 = 0x06; - - public static final int OBEX_AUTH_REALM_CHARSET_ISO_8859_7 = 0x07; - - public static final int OBEX_AUTH_REALM_CHARSET_ISO_8859_8 = 0x08; - - public static final int OBEX_AUTH_REALM_CHARSET_ISO_8859_9 = 0x09; - - public static final int OBEX_AUTH_REALM_CHARSET_UNICODE = 0xFF; - - public static final byte OBEX_SRM_ENABLE = 0x01; // For BT we only need enable/disable - public static final byte OBEX_SRM_DISABLE = 0x00; - public static final byte OBEX_SRM_SUPPORT = 0x02; // Unused for now - - public static final byte OBEX_SRMP_WAIT = 0x01; // Only SRMP value used by BT - - /** - * Updates the HeaderSet with the headers received in the byte array - * provided. Invalid headers are ignored. - *

- * The first two bits of an OBEX Header specifies the type of object that is - * being sent. The table below specifies the meaning of the high bits. - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - *
Bits 8 and 7ValueDescription
000x00Null Terminated Unicode text, prefixed with 2 byte unsigned integer
010x40Byte Sequence, length prefixed with 2 byte unsigned integer
100x801 byte quantity
110xC04 byte quantity - transmitted in network byte order (high byte first
- * This method uses the information in this table to determine the type of - * Java object to create and passes that object with the full header to - * setHeader() to update the HeaderSet object. Invalid headers will cause an - * exception to be thrown. When it is thrown, it is ignored. - * @param header the HeaderSet to update - * @param headerArray the byte array containing headers - * @return the result of the last start body or end body header provided; - * the first byte in the result will specify if a body or end of - * body is received - * @throws IOException if an invalid header was found - */ - public static byte[] updateHeaderSet(HeaderSet header, byte[] headerArray) throws IOException { - int index = 0; - int length = 0; - int headerID; - byte[] value = null; - byte[] body = null; - HeaderSet headerImpl = header; - try { - while (index < headerArray.length) { - headerID = 0xFF & headerArray[index]; - switch (headerID & (0xC0)) { - - /* - * 0x00 is a unicode null terminate string with the first - * two bytes after the header identifier being the length - */ - case 0x00: - // Fall through - /* - * 0x40 is a byte sequence with the first - * two bytes after the header identifier being the length - */ - case 0x40: - boolean trimTail = true; - index++; - length = ((0xFF & headerArray[index]) << 8) + - (0xFF & headerArray[index + 1]); - index += 2; - if (length <= OBEX_BYTE_SEQ_HEADER_LEN) { - Log.e(TAG, "Remote sent an OBEX packet with " + - "incorrect header length = " + length); - break; - } - length -= OBEX_BYTE_SEQ_HEADER_LEN; - value = new byte[length]; - System.arraycopy(headerArray, index, value, 0, length); - if (length == 0 || (length > 0 && (value[length - 1] != 0))) { - trimTail = false; - } - switch (headerID) { - case HeaderSet.TYPE: - try { - // Remove trailing null - if (trimTail == false) { - headerImpl.setHeader(headerID, new String(value, 0, - value.length, "ISO8859_1")); - } else { - headerImpl.setHeader(headerID, new String(value, 0, - value.length - 1, "ISO8859_1")); - } - } catch (UnsupportedEncodingException e) { - throw e; - } - break; - - case HeaderSet.AUTH_CHALLENGE: - headerImpl.mAuthChall = new byte[length]; - System.arraycopy(headerArray, index, headerImpl.mAuthChall, 0, - length); - break; - - case HeaderSet.AUTH_RESPONSE: - headerImpl.mAuthResp = new byte[length]; - System.arraycopy(headerArray, index, headerImpl.mAuthResp, 0, - length); - break; - - case HeaderSet.BODY: - /* Fall Through */ - case HeaderSet.END_OF_BODY: - body = new byte[length + 1]; - body[0] = (byte)headerID; - System.arraycopy(headerArray, index, body, 1, length); - break; - - case HeaderSet.TIME_ISO_8601: - try { - String dateString = new String(value, "ISO8859_1"); - Calendar temp = Calendar.getInstance(); - if ((dateString.length() == 16) - && (dateString.charAt(15) == 'Z')) { - temp.setTimeZone(TimeZone.getTimeZone("UTC")); - } - temp.set(Calendar.YEAR, Integer.parseInt(dateString.substring( - 0, 4))); - temp.set(Calendar.MONTH, Integer.parseInt(dateString.substring( - 4, 6))); - temp.set(Calendar.DAY_OF_MONTH, Integer.parseInt(dateString - .substring(6, 8))); - temp.set(Calendar.HOUR_OF_DAY, Integer.parseInt(dateString - .substring(9, 11))); - temp.set(Calendar.MINUTE, Integer.parseInt(dateString - .substring(11, 13))); - temp.set(Calendar.SECOND, Integer.parseInt(dateString - .substring(13, 15))); - headerImpl.setHeader(HeaderSet.TIME_ISO_8601, temp); - } catch (UnsupportedEncodingException e) { - throw e; - } - break; - - default: - if ((headerID & 0xC0) == 0x00) { - headerImpl.setHeader(headerID, ObexHelper.convertToUnicode( - value, true)); - } else { - headerImpl.setHeader(headerID, value); - } - } - - index += length; - break; - - /* - * 0x80 is a byte header. The only valid byte headers are - * the 16 user defined byte headers. - */ - case 0x80: - index++; - try { - headerImpl.setHeader(headerID, Byte.valueOf(headerArray[index])); - } catch (Exception e) { - // Not a valid header so ignore - } - index++; - break; - - /* - * 0xC0 is a 4 byte unsigned integer header and with the - * exception of TIME_4_BYTE will be converted to a Long - * and added. - */ - case 0xC0: - index++; - value = new byte[4]; - System.arraycopy(headerArray, index, value, 0, 4); - try { - if (headerID != HeaderSet.TIME_4_BYTE) { - // Determine if it is a connection ID. These - // need to be handled differently - if (headerID == HeaderSet.CONNECTION_ID) { - headerImpl.mConnectionID = new byte[4]; - System.arraycopy(value, 0, headerImpl.mConnectionID, 0, 4); - } else { - headerImpl.setHeader(headerID, Long - .valueOf(convertToLong(value))); - } - } else { - Calendar temp = Calendar.getInstance(); - temp.setTime(new Date(convertToLong(value) * 1000L)); - headerImpl.setHeader(HeaderSet.TIME_4_BYTE, temp); - } - } catch (Exception e) { - // Not a valid header so ignore - throw new IOException("Header was not formatted properly", e); - } - index += 4; - break; - } - - } - } catch (IOException e) { - throw new IOException("Header was not formatted properly", e); - } - - return body; - } - - /** - * Creates the header part of OBEX packet based on the header provided. - * TODO: Could use getHeaderList() to get the array of headers to include - * and then use the high two bits to determine the the type of the object - * and construct the byte array from that. This will make the size smaller. - * @param head the header used to construct the byte array - * @param nullOut true if the header should be set to - * null once it is added to the array or - * false if it should not be nulled out - * @return the header of an OBEX packet - */ - public static byte[] createHeader(HeaderSet head, boolean nullOut) { - Long intHeader = null; - String stringHeader = null; - Calendar dateHeader = null; - Byte byteHeader = null; - StringBuffer buffer = null; - byte[] value = null; - byte[] result = null; - byte[] lengthArray = new byte[2]; - int length; - HeaderSet headImpl = null; - ByteArrayOutputStream out = new ByteArrayOutputStream(); - headImpl = head; - - try { - /* - * Determine if there is a connection ID to send. If there is, - * then it should be the first header in the packet. - */ - if ((headImpl.mConnectionID != null) && (headImpl.getHeader(HeaderSet.TARGET) == null)) { - - out.write((byte)HeaderSet.CONNECTION_ID); - out.write(headImpl.mConnectionID); - } - - // Count Header - intHeader = (Long)headImpl.getHeader(HeaderSet.COUNT); - if (intHeader != null) { - out.write((byte)HeaderSet.COUNT); - value = ObexHelper.convertToByteArray(intHeader.longValue()); - out.write(value); - if (nullOut) { - headImpl.setHeader(HeaderSet.COUNT, null); - } - } - - // Name Header - stringHeader = (String)headImpl.getHeader(HeaderSet.NAME); - if (stringHeader != null) { - out.write((byte)HeaderSet.NAME); - value = ObexHelper.convertToUnicodeByteArray(stringHeader); - length = value.length + 3; - lengthArray[0] = (byte)(0xFF & (length >> 8)); - lengthArray[1] = (byte)(0xFF & length); - out.write(lengthArray); - out.write(value); - if (nullOut) { - headImpl.setHeader(HeaderSet.NAME, null); - } - } else if (headImpl.getEmptyNameHeader()) { - out.write((byte) HeaderSet.NAME); - lengthArray[0] = (byte) 0x00; - lengthArray[1] = (byte) 0x03; - out.write(lengthArray); - } - - // Type Header - stringHeader = (String)headImpl.getHeader(HeaderSet.TYPE); - if (stringHeader != null) { - out.write((byte)HeaderSet.TYPE); - try { - value = stringHeader.getBytes("ISO8859_1"); - } catch (UnsupportedEncodingException e) { - throw e; - } - - length = value.length + 4; - lengthArray[0] = (byte)(255 & (length >> 8)); - lengthArray[1] = (byte)(255 & length); - out.write(lengthArray); - out.write(value); - out.write(0x00); - if (nullOut) { - headImpl.setHeader(HeaderSet.TYPE, null); - } - } - - // Length Header - intHeader = (Long)headImpl.getHeader(HeaderSet.LENGTH); - if (intHeader != null) { - out.write((byte)HeaderSet.LENGTH); - value = ObexHelper.convertToByteArray(intHeader.longValue()); - out.write(value); - if (nullOut) { - headImpl.setHeader(HeaderSet.LENGTH, null); - } - } - - // Time ISO Header - dateHeader = (Calendar)headImpl.getHeader(HeaderSet.TIME_ISO_8601); - if (dateHeader != null) { - - /* - * The ISO Header should take the form YYYYMMDDTHHMMSSZ. The - * 'Z' will only be included if it is a UTC time. - */ - buffer = new StringBuffer(); - int temp = dateHeader.get(Calendar.YEAR); - for (int i = temp; i < 1000; i = i * 10) { - buffer.append("0"); - } - buffer.append(temp); - temp = dateHeader.get(Calendar.MONTH); - if (temp < 10) { - buffer.append("0"); - } - buffer.append(temp); - temp = dateHeader.get(Calendar.DAY_OF_MONTH); - if (temp < 10) { - buffer.append("0"); - } - buffer.append(temp); - buffer.append("T"); - temp = dateHeader.get(Calendar.HOUR_OF_DAY); - if (temp < 10) { - buffer.append("0"); - } - buffer.append(temp); - temp = dateHeader.get(Calendar.MINUTE); - if (temp < 10) { - buffer.append("0"); - } - buffer.append(temp); - temp = dateHeader.get(Calendar.SECOND); - if (temp < 10) { - buffer.append("0"); - } - buffer.append(temp); - - if (dateHeader.getTimeZone().getID().equals("UTC")) { - buffer.append("Z"); - } - - try { - value = buffer.toString().getBytes("ISO8859_1"); - } catch (UnsupportedEncodingException e) { - throw e; - } - - length = value.length + 3; - lengthArray[0] = (byte)(255 & (length >> 8)); - lengthArray[1] = (byte)(255 & length); - out.write(HeaderSet.TIME_ISO_8601); - out.write(lengthArray); - out.write(value); - if (nullOut) { - headImpl.setHeader(HeaderSet.TIME_ISO_8601, null); - } - } - - // Time 4 Byte Header - dateHeader = (Calendar)headImpl.getHeader(HeaderSet.TIME_4_BYTE); - if (dateHeader != null) { - out.write(HeaderSet.TIME_4_BYTE); - - /* - * Need to call getTime() twice. The first call will return - * a java.util.Date object. The second call returns the number - * of milliseconds since January 1, 1970. We need to convert - * it to seconds since the TIME_4_BYTE expects the number of - * seconds since January 1, 1970. - */ - value = ObexHelper.convertToByteArray(dateHeader.getTime().getTime() / 1000L); - out.write(value); - if (nullOut) { - headImpl.setHeader(HeaderSet.TIME_4_BYTE, null); - } - } - - // Description Header - stringHeader = (String)headImpl.getHeader(HeaderSet.DESCRIPTION); - if (stringHeader != null) { - out.write((byte)HeaderSet.DESCRIPTION); - value = ObexHelper.convertToUnicodeByteArray(stringHeader); - length = value.length + 3; - lengthArray[0] = (byte)(255 & (length >> 8)); - lengthArray[1] = (byte)(255 & length); - out.write(lengthArray); - out.write(value); - if (nullOut) { - headImpl.setHeader(HeaderSet.DESCRIPTION, null); - } - } - - // Target Header - value = (byte[])headImpl.getHeader(HeaderSet.TARGET); - if (value != null) { - out.write((byte)HeaderSet.TARGET); - length = value.length + 3; - lengthArray[0] = (byte)(255 & (length >> 8)); - lengthArray[1] = (byte)(255 & length); - out.write(lengthArray); - out.write(value); - if (nullOut) { - headImpl.setHeader(HeaderSet.TARGET, null); - } - } - - // HTTP Header - value = (byte[])headImpl.getHeader(HeaderSet.HTTP); - if (value != null) { - out.write((byte)HeaderSet.HTTP); - length = value.length + 3; - lengthArray[0] = (byte)(255 & (length >> 8)); - lengthArray[1] = (byte)(255 & length); - out.write(lengthArray); - out.write(value); - if (nullOut) { - headImpl.setHeader(HeaderSet.HTTP, null); - } - } - - // Who Header - value = (byte[])headImpl.getHeader(HeaderSet.WHO); - if (value != null) { - out.write((byte)HeaderSet.WHO); - length = value.length + 3; - lengthArray[0] = (byte)(255 & (length >> 8)); - lengthArray[1] = (byte)(255 & length); - out.write(lengthArray); - out.write(value); - if (nullOut) { - headImpl.setHeader(HeaderSet.WHO, null); - } - } - - // Connection ID Header - value = (byte[])headImpl.getHeader(HeaderSet.APPLICATION_PARAMETER); - if (value != null) { - out.write((byte)HeaderSet.APPLICATION_PARAMETER); - length = value.length + 3; - lengthArray[0] = (byte)(255 & (length >> 8)); - lengthArray[1] = (byte)(255 & length); - out.write(lengthArray); - out.write(value); - if (nullOut) { - headImpl.setHeader(HeaderSet.APPLICATION_PARAMETER, null); - } - } - - // Object Class Header - value = (byte[])headImpl.getHeader(HeaderSet.OBJECT_CLASS); - if (value != null) { - out.write((byte)HeaderSet.OBJECT_CLASS); - length = value.length + 3; - lengthArray[0] = (byte)(255 & (length >> 8)); - lengthArray[1] = (byte)(255 & length); - out.write(lengthArray); - out.write(value); - if (nullOut) { - headImpl.setHeader(HeaderSet.OBJECT_CLASS, null); - } - } - - // Check User Defined Headers - for (int i = 0; i < 16; i++) { - - //Unicode String Header - stringHeader = (String)headImpl.getHeader(i + 0x30); - if (stringHeader != null) { - out.write((byte)i + 0x30); - value = ObexHelper.convertToUnicodeByteArray(stringHeader); - length = value.length + 3; - lengthArray[0] = (byte)(255 & (length >> 8)); - lengthArray[1] = (byte)(255 & length); - out.write(lengthArray); - out.write(value); - if (nullOut) { - headImpl.setHeader(i + 0x30, null); - } - } - - // Byte Sequence Header - value = (byte[])headImpl.getHeader(i + 0x70); - if (value != null) { - out.write((byte)i + 0x70); - length = value.length + 3; - lengthArray[0] = (byte)(255 & (length >> 8)); - lengthArray[1] = (byte)(255 & length); - out.write(lengthArray); - out.write(value); - if (nullOut) { - headImpl.setHeader(i + 0x70, null); - } - } - - // Byte Header - byteHeader = (Byte)headImpl.getHeader(i + 0xB0); - if (byteHeader != null) { - out.write((byte)i + 0xB0); - out.write(byteHeader.byteValue()); - if (nullOut) { - headImpl.setHeader(i + 0xB0, null); - } - } - - // Integer header - intHeader = (Long)headImpl.getHeader(i + 0xF0); - if (intHeader != null) { - out.write((byte)i + 0xF0); - out.write(ObexHelper.convertToByteArray(intHeader.longValue())); - if (nullOut) { - headImpl.setHeader(i + 0xF0, null); - } - } - } - - // Add the authentication challenge header - if (headImpl.mAuthChall != null) { - out.write((byte)HeaderSet.AUTH_CHALLENGE); - length = headImpl.mAuthChall.length + 3; - lengthArray[0] = (byte)(255 & (length >> 8)); - lengthArray[1] = (byte)(255 & length); - out.write(lengthArray); - out.write(headImpl.mAuthChall); - if (nullOut) { - headImpl.mAuthChall = null; - } - } - - // Add the authentication response header - if (headImpl.mAuthResp != null) { - out.write((byte)HeaderSet.AUTH_RESPONSE); - length = headImpl.mAuthResp.length + 3; - lengthArray[0] = (byte)(255 & (length >> 8)); - lengthArray[1] = (byte)(255 & length); - out.write(lengthArray); - out.write(headImpl.mAuthResp); - if (nullOut) { - headImpl.mAuthResp = null; - } - } - - // TODO: - // If the SRM and SRMP header is in use, they must be send in the same OBEX packet - // But the current structure of the obex code cannot handle this, and therefore - // it makes sense to put them in the tail of the headers, since we then reduce the - // chance of enabling SRM to soon. The down side is that SRM cannot be used while - // transferring non-body headers - - // Add the SRM header - byteHeader = (Byte)headImpl.getHeader(HeaderSet.SINGLE_RESPONSE_MODE); - if (byteHeader != null) { - out.write((byte)HeaderSet.SINGLE_RESPONSE_MODE); - out.write(byteHeader.byteValue()); - if (nullOut) { - headImpl.setHeader(HeaderSet.SINGLE_RESPONSE_MODE, null); - } - } - - // Add the SRM parameter header - byteHeader = (Byte)headImpl.getHeader(HeaderSet.SINGLE_RESPONSE_MODE_PARAMETER); - if (byteHeader != null) { - out.write((byte)HeaderSet.SINGLE_RESPONSE_MODE_PARAMETER); - out.write(byteHeader.byteValue()); - if (nullOut) { - headImpl.setHeader(HeaderSet.SINGLE_RESPONSE_MODE_PARAMETER, null); - } - } - - } catch (IOException e) { - } finally { - result = out.toByteArray(); - try { - out.close(); - } catch (Exception ex) { - } - } - - return result; - - } - - /** - * Determines where the maximum divide is between headers. This method is - * used by put and get operations to separate headers to a size that meets - * the max packet size allowed. - * @param headerArray the headers to separate - * @param start the starting index to search - * @param maxSize the maximum size of a packet - * @return the index of the end of the header block to send or -1 if the - * header could not be divided because the header is too large - */ - public static int findHeaderEnd(byte[] headerArray, int start, int maxSize) { - - int fullLength = 0; - int lastLength = -1; - int index = start; - int length = 0; - - // TODO: Ensure SRM and SRMP headers are not split into two OBEX packets - - while ((fullLength < maxSize) && (index < headerArray.length)) { - int headerID = (headerArray[index] < 0 ? headerArray[index] + 256 : headerArray[index]); - lastLength = fullLength; - - switch (headerID & (0xC0)) { - - case 0x00: - // Fall through - case 0x40: - - index++; - length = (headerArray[index] < 0 ? headerArray[index] + 256 - : headerArray[index]); - length = length << 8; - index++; - length += (headerArray[index] < 0 ? headerArray[index] + 256 - : headerArray[index]); - length -= 3; - index++; - index += length; - fullLength += length + 3; - break; - - case 0x80: - - index++; - index++; - fullLength += 2; - break; - - case 0xC0: - - index += 5; - fullLength += 5; - break; - - } - - } - - /* - * Determine if this is the last header or not - */ - if (lastLength == 0) { - /* - * Since this is the last header, check to see if the size of this - * header is less then maxSize. If it is, return the length of the - * header, otherwise return -1. The length of the header is - * returned since it would be the start of the next header - */ - if (fullLength < maxSize) { - return headerArray.length; - } else { - return -1; - } - } else { - return lastLength + start; - } - } - - /** - * Converts the byte array to a long. - * @param b the byte array to convert to a long - * @return the byte array as a long - */ - public static long convertToLong(byte[] b) { - long result = 0; - long value = 0; - long power = 0; - - for (int i = (b.length - 1); i >= 0; i--) { - value = b[i]; - if (value < 0) { - value += 256; - } - - result = result | (value << power); - power += 8; - } - - return result; - } - - /** - * Converts the long to a 4 byte array. The long must be non negative. - * @param l the long to convert - * @return a byte array that is the same as the long - */ - public static byte[] convertToByteArray(long l) { - byte[] b = new byte[4]; - - b[0] = (byte)(255 & (l >> 24)); - b[1] = (byte)(255 & (l >> 16)); - b[2] = (byte)(255 & (l >> 8)); - b[3] = (byte)(255 & l); - - return b; - } - - /** - * Converts the String to a UNICODE byte array. It will also add the ending - * null characters to the end of the string. - * @param s the string to convert - * @return the unicode byte array of the string - */ - public static byte[] convertToUnicodeByteArray(String s) { - if (s == null) { - return null; - } - - char c[] = s.toCharArray(); - byte[] result = new byte[(c.length * 2) + 2]; - for (int i = 0; i < c.length; i++) { - result[(i * 2)] = (byte)(c[i] >> 8); - result[((i * 2) + 1)] = (byte)c[i]; - } - - // Add the UNICODE null character - result[result.length - 2] = 0; - result[result.length - 1] = 0; - - return result; - } - - /** - * Retrieves the value from the byte array for the tag value specified. The - * array should be of the form Tag - Length - Value triplet. - * @param tag the tag to retrieve from the byte array - * @param triplet the byte sequence containing the tag length value form - * @return the value of the specified tag - */ - public static byte[] getTagValue(byte tag, byte[] triplet) { - - int index = findTag(tag, triplet); - if (index == -1) { - return null; - } - - index++; - int length = triplet[index] & 0xFF; - - byte[] result = new byte[length]; - index++; - System.arraycopy(triplet, index, result, 0, length); - - return result; - } - - /** - * Finds the index that starts the tag value pair in the byte array provide. - * @param tag the tag to look for - * @param value the byte array to search - * @return the starting index of the tag or -1 if the tag could not be found - */ - public static int findTag(byte tag, byte[] value) { - int length = 0; - - if (value == null) { - return -1; - } - - int index = 0; - - while ((index < value.length) && (value[index] != tag)) { - length = value[index + 1] & 0xFF; - index += length + 2; - } - - if (index >= value.length) { - return -1; - } - - return index; - } - - /** - * Converts the byte array provided to a unicode string. - * @param b the byte array to convert to a string - * @param includesNull determine if the byte string provided contains the - * UNICODE null character at the end or not; if it does, it will be - * removed - * @return a Unicode string - * @throws IllegalArgumentException if the byte array has an odd length - */ - public static String convertToUnicode(byte[] b, boolean includesNull) { - if (b == null || b.length == 0) { - return null; - } - int arrayLength = b.length; - if (!((arrayLength % 2) == 0)) { - throw new IllegalArgumentException("Byte array not of a valid form"); - } - arrayLength = (arrayLength >> 1); - if (includesNull) { - arrayLength -= 1; - } - - char[] c = new char[arrayLength]; - for (int i = 0; i < arrayLength; i++) { - int upper = b[2 * i]; - int lower = b[(2 * i) + 1]; - if (upper < 0) { - upper += 256; - } - if (lower < 0) { - lower += 256; - } - // If upper and lower both equal 0, it should be the end of string. - // Ignore left bytes from array to avoid potential issues - if (upper == 0 && lower == 0) { - return new String(c, 0, i); - } - - c[i] = (char)((upper << 8) | lower); - } - - return new String(c); - } - - /** - * Compute the MD5 hash of the byte array provided. Does not accumulate - * input. - * @param in the byte array to hash - * @return the MD5 hash of the byte array - */ - public static byte[] computeMd5Hash(byte[] in) { - try { - MessageDigest md5 = MessageDigest.getInstance("MD5"); - return md5.digest(in); - } catch (NoSuchAlgorithmException e) { - throw new RuntimeException(e); - } - } - - /** - * Computes an authentication challenge header. - * @param nonce the challenge that will be provided to the peer; the - * challenge must be 16 bytes long - * @param realm a short description that describes what password to use - * @param access if true then full access will be granted if - * successful; if false then read only access will be - * granted if successful - * @param userID if true, a user ID is required in the reply; - * if false, no user ID is required - * @throws IllegalArgumentException if the challenge is not 16 bytes long; - * if the realm can not be encoded in less then 255 bytes - * @throws IOException if the encoding scheme ISO 8859-1 is not supported - */ - public static byte[] computeAuthenticationChallenge(byte[] nonce, String realm, boolean access, - boolean userID) throws IOException { - byte[] authChall = null; - - if (nonce.length != 16) { - throw new IllegalArgumentException("Nonce must be 16 bytes long"); - } - - /* - * The authentication challenge is a byte sequence of the following form - * byte 0: 0x00 - the tag for the challenge - * byte 1: 0x10 - the length of the challenge; must be 16 - * byte 2-17: the authentication challenge - * byte 18: 0x01 - the options tag; this is optional in the spec, but - * we are going to include it in every message - * byte 19: 0x01 - length of the options; must be 1 - * byte 20: the value of the options; bit 0 is set if user ID is - * required; bit 1 is set if access mode is read only - * byte 21: 0x02 - the tag for authentication realm; only included if - * an authentication realm is specified - * byte 22: the length of the authentication realm; only included if - * the authentication realm is specified - * byte 23: the encoding scheme of the authentication realm; we will use - * the ISO 8859-1 encoding scheme since it is part of the KVM - * byte 24 & up: the realm if one is specified. - */ - if (realm == null) { - authChall = new byte[21]; - } else { - if (realm.length() >= 255) { - throw new IllegalArgumentException("Realm must be less then 255 bytes"); - } - authChall = new byte[24 + realm.length()]; - authChall[21] = 0x02; - authChall[22] = (byte)(realm.length() + 1); - authChall[23] = 0x01; // ISO 8859-1 Encoding - System.arraycopy(realm.getBytes("ISO8859_1"), 0, authChall, 24, realm.length()); - } - - // Include the nonce field in the header - authChall[0] = 0x00; - authChall[1] = 0x10; - System.arraycopy(nonce, 0, authChall, 2, 16); - - // Include the options header - authChall[18] = 0x01; - authChall[19] = 0x01; - authChall[20] = 0x00; - - if (!access) { - authChall[20] = (byte)(authChall[20] | 0x02); - } - if (userID) { - authChall[20] = (byte)(authChall[20] | 0x01); - } - - return authChall; - } - - /** - * Return the maximum allowed OBEX packet to transmit. - * OBEX packets transmitted must be smaller than this value. - * @param transport Reference to the ObexTransport in use. - * @return the maximum allowed OBEX packet to transmit - */ - public static int getMaxTxPacketSize(ObexTransport transport) { - int size = transport.getMaxTransmitPacketSize(); - return validateMaxPacketSize(size); - } - - /** - * Return the maximum allowed OBEX packet to receive - used in OBEX connect. - * @param transport - * @return he maximum allowed OBEX packet to receive - */ - public static int getMaxRxPacketSize(ObexTransport transport) { - int size = transport.getMaxReceivePacketSize(); - return validateMaxPacketSize(size); - } - - private static int validateMaxPacketSize(int size) { - if (VDBG && (size > MAX_PACKET_SIZE_INT)) { - Log.w(TAG, "The packet size supported for the connection (" + size + ") is larger" - + " than the configured OBEX packet size: " + MAX_PACKET_SIZE_INT); - } - if (size != -1 && size < MAX_PACKET_SIZE_INT) { - if (size < LOWER_LIMIT_MAX_PACKET_SIZE) { - throw new IllegalArgumentException(size + " is less that the lower limit: " - + LOWER_LIMIT_MAX_PACKET_SIZE); - } - return size; - } - return MAX_PACKET_SIZE_INT; - } -} diff --git a/obex/javax/obex/ObexSession.java b/obex/javax/obex/ObexSession.java deleted file mode 100644 index 542b9c8b2492..000000000000 --- a/obex/javax/obex/ObexSession.java +++ /dev/null @@ -1,224 +0,0 @@ -/* - * Copyright (c) 2008-2009, Motorola, Inc. - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * - Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * - Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * - Neither the name of the Motorola, Inc. nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -package javax.obex; - -import java.io.IOException; - -import android.util.Log; - -/** - * The ObexSession interface characterizes the term - * "OBEX Connection" as defined in the IrDA Object Exchange Protocol v1.2, which - * could be the server-side view of an OBEX connection, or the client-side view - * of the same connection, which is established by server's accepting of a - * client issued "CONNECT". - *

- * This interface serves as the common super class for - * ClientSession and ServerSession. - * @hide - */ -public class ObexSession { - - private static final String TAG = "ObexSession"; - private static final boolean V = ObexHelper.VDBG; - - protected Authenticator mAuthenticator; - - protected byte[] mChallengeDigest; - - /** - * Called when the server received an authentication challenge header. This - * will cause the authenticator to handle the authentication challenge. - * @param header the header with the authentication challenge - * @return true if the last request should be resent; - * false if the last request should not be resent - * @throws IOException - */ - public boolean handleAuthChall(HeaderSet header) throws IOException { - if (mAuthenticator == null) { - return false; - } - - /* - * An authentication challenge is made up of one required and two - * optional tag length value triplets. The tag 0x00 is required to be in - * the authentication challenge and it represents the challenge digest - * that was received. The tag 0x01 is the options tag. This tag tracks - * if user ID is required and if full access will be granted. The tag - * 0x02 is the realm, which provides a description of which user name - * and password to use. - */ - byte[] challenge = ObexHelper.getTagValue((byte)0x00, header.mAuthChall); - byte[] option = ObexHelper.getTagValue((byte)0x01, header.mAuthChall); - byte[] description = ObexHelper.getTagValue((byte)0x02, header.mAuthChall); - - String realm = null; - if (description != null) { - byte[] realmString = new byte[description.length - 1]; - System.arraycopy(description, 1, realmString, 0, realmString.length); - - switch (description[0] & 0xFF) { - - case ObexHelper.OBEX_AUTH_REALM_CHARSET_ASCII: - // ASCII encoding - // Fall through - case ObexHelper.OBEX_AUTH_REALM_CHARSET_ISO_8859_1: - // ISO-8859-1 encoding - try { - realm = new String(realmString, "ISO8859_1"); - } catch (Exception e) { - throw new IOException("Unsupported Encoding Scheme"); - } - break; - - case ObexHelper.OBEX_AUTH_REALM_CHARSET_UNICODE: - // UNICODE Encoding - realm = ObexHelper.convertToUnicode(realmString, false); - break; - - default: - throw new IOException("Unsupported Encoding Scheme"); - } - } - - boolean isUserIDRequired = false; - boolean isFullAccess = true; - if (option != null) { - if ((option[0] & 0x01) != 0) { - isUserIDRequired = true; - } - - if ((option[0] & 0x02) != 0) { - isFullAccess = false; - } - } - - PasswordAuthentication result = null; - header.mAuthChall = null; - - try { - result = mAuthenticator - .onAuthenticationChallenge(realm, isUserIDRequired, isFullAccess); - } catch (Exception e) { - if (V) Log.d(TAG, "Exception occured - returning false", e); - return false; - } - - /* - * If no password is provided then we not resent the request - */ - if (result == null) { - return false; - } - - byte[] password = result.getPassword(); - if (password == null) { - return false; - } - - byte[] userName = result.getUserName(); - - /* - * Create the authentication response header. It includes 1 required and - * 2 option tag length value triples. The required triple has a tag of - * 0x00 and is the response digest. The first optional tag is 0x01 and - * represents the user ID. If no user ID is provided, then no user ID - * will be sent. The second optional tag is 0x02 and is the challenge - * that was received. This will always be sent - */ - if (userName != null) { - header.mAuthResp = new byte[38 + userName.length]; - header.mAuthResp[36] = (byte)0x01; - header.mAuthResp[37] = (byte)userName.length; - System.arraycopy(userName, 0, header.mAuthResp, 38, userName.length); - } else { - header.mAuthResp = new byte[36]; - } - - // Create the secret String - byte[] digest = new byte[challenge.length + password.length + 1]; - System.arraycopy(challenge, 0, digest, 0, challenge.length); - // Insert colon between challenge and password - digest[challenge.length] = (byte)0x3A; - System.arraycopy(password, 0, digest, challenge.length + 1, password.length); - - // Add the Response Digest - header.mAuthResp[0] = (byte)0x00; - header.mAuthResp[1] = (byte)0x10; - - System.arraycopy(ObexHelper.computeMd5Hash(digest), 0, header.mAuthResp, 2, 16); - - // Add the challenge - header.mAuthResp[18] = (byte)0x02; - header.mAuthResp[19] = (byte)0x10; - System.arraycopy(challenge, 0, header.mAuthResp, 20, 16); - - return true; - } - - /** - * Called when the server received an authentication response header. This - * will cause the authenticator to handle the authentication response. - * @param authResp the authentication response - * @return true if the response passed; false if - * the response failed - */ - public boolean handleAuthResp(byte[] authResp) { - if (mAuthenticator == null) { - return false; - } - // get the correct password from the application - byte[] correctPassword = mAuthenticator.onAuthenticationResponse(ObexHelper.getTagValue( - (byte)0x01, authResp)); - if (correctPassword == null) { - return false; - } - - byte[] temp = new byte[correctPassword.length + 16]; - - System.arraycopy(mChallengeDigest, 0, temp, 0, 16); - System.arraycopy(correctPassword, 0, temp, 16, correctPassword.length); - - byte[] correctResponse = ObexHelper.computeMd5Hash(temp); - byte[] actualResponse = ObexHelper.getTagValue((byte)0x00, authResp); - - // compare the MD5 hash array . - for (int i = 0; i < 16; i++) { - if (correctResponse[i] != actualResponse[i]) { - return false; - } - } - - return true; - } -} diff --git a/obex/javax/obex/ObexTransport.java b/obex/javax/obex/ObexTransport.java deleted file mode 100644 index 4cef0b33df4f..000000000000 --- a/obex/javax/obex/ObexTransport.java +++ /dev/null @@ -1,113 +0,0 @@ -/* - * Copyright (c) 2008-2009, Motorola, Inc. - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * - Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * - Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * - Neither the name of the Motorola, Inc. nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -package javax.obex; - -import java.io.DataInputStream; -import java.io.DataOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; - -/** - * The ObexTransport interface defines the underlying transport - * connection which carries the OBEX protocol( such as TCP, RFCOMM device file - * exposed by Bluetooth or USB in kernel, RFCOMM socket emulated in Android - * platform, Irda). This interface provides an abstract layer to be used by the - * ObexConnection. Each kind of medium shall have its own - * implementation to wrap and follow the same interface. - *

- * See section 1.2.2 of IrDA Object Exchange Protocol specification. - *

- * Different kind of medium may have different construction - for example, the - * RFCOMM device file medium may be constructed from a file descriptor or simply - * a string while the TCP medium usually from a socket. - * @hide - */ -public interface ObexTransport { - - void create() throws IOException; - - void listen() throws IOException; - - void close() throws IOException; - - void connect() throws IOException; - - void disconnect() throws IOException; - - InputStream openInputStream() throws IOException; - - OutputStream openOutputStream() throws IOException; - - DataInputStream openDataInputStream() throws IOException; - - DataOutputStream openDataOutputStream() throws IOException; - - /** - * Must return the maximum allowed OBEX packet that can be sent over - * the transport. For L2CAP this will be the Max SDU reported by the - * peer device. - * The returned value will be used to set the outgoing OBEX packet - * size. Therefore this value shall not change. - * For RFCOMM or other transport types where the OBEX packets size - * is unrelated to the transport packet size, return -1; - * Exception can be made (like PBAP transport) with a smaller value - * to avoid bad effect on other profiles using the RFCOMM; - * @return the maximum allowed OBEX packet that can be send over - * the transport. Or -1 in case of don't care. - */ - int getMaxTransmitPacketSize(); - - /** - * Must return the maximum allowed OBEX packet that can be received over - * the transport. For L2CAP this will be the Max SDU configured for the - * L2CAP channel. - * The returned value will be used to validate the incoming packet size - * values. - * For RFCOMM or other transport types where the OBEX packets size - * is unrelated to the transport packet size, return -1; - * @return the maximum allowed OBEX packet that can be send over - * the transport. Or -1 in case of don't care. - */ - int getMaxReceivePacketSize(); - - /** - * Shall return true if the transport in use supports SRM. - * @return - * true if SRM operation is supported, and is to be enabled. - * false if SRM operations are not supported, or should not be used. - */ - boolean isSrmSupported(); - - -} diff --git a/obex/javax/obex/Operation.java b/obex/javax/obex/Operation.java deleted file mode 100644 index 5b4d5ace3669..000000000000 --- a/obex/javax/obex/Operation.java +++ /dev/null @@ -1,183 +0,0 @@ -/* - * Copyright (c) 2008-2009, Motorola, Inc. - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * - Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * - Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * - Neither the name of the Motorola, Inc. nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -package javax.obex; - -import java.io.DataInputStream; -import java.io.DataOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; - -/** - * The Operation interface provides ways to manipulate a single - * OBEX PUT or GET operation. The implementation of this interface sends OBEX - * packets as they are built. If during the operation the peer in the operation - * ends the operation, an IOException is thrown on the next read - * from the input stream, write to the output stream, or call to - * sendHeaders(). - *

- * Definition of methods inherited from ContentConnection - * - *

- * getEncoding() will always return null.
- * getLength() will return the length specified by the OBEX Length - * header or -1 if the OBEX Length header was not included.
- * getType() will return the value specified in the OBEX Type - * header or null if the OBEX Type header was not included.
- *

- * How Headers are Handled - *

- * As headers are received, they may be retrieved through the - * getReceivedHeaders() method. If new headers are set during the - * operation, the new headers will be sent during the next packet exchange. - *

- * PUT example - *

- *

- * void putObjectViaOBEX(ClientSession conn, HeaderSet head, byte[] obj) throws IOException {
- *     // Include the length header
- *     head.setHeader(head.LENGTH, new Long(obj.length));
- *     // Initiate the PUT request
- *     Operation op = conn.put(head);
- *     // Open the output stream to put the object to it
- *     DataOutputStream out = op.openDataOutputStream();
- *     // Send the object to the server
- *     out.write(obj);
- *     // End the transaction
- *     out.close();
- *     op.close();
- * }
- * 
- *

- * GET example - *

- *

- * byte[] getObjectViaOBEX(ClientSession conn, HeaderSet head) throws IOException {
- *     // Send the initial GET request to the server
- *     Operation op = conn.get(head);
- *     // Retrieve the length of the object being sent back
- *     int length = op.getLength();
- *     // Create space for the object
- *     byte[] obj = new byte[length];
- *     // Get the object from the input stream
- *     DataInputStream in = trans.openDataInputStream();
- *     in.read(obj);
- *     // End the transaction
- *     in.close();
- *     op.close();
- *     return obj;
- * }
- * 
- * - *

Client PUT Operation Flow

For PUT operations, a call to - * close() the OutputStream returned from - * openOutputStream() or openDataOutputStream() will - * signal that the request is done. (In OBEX terms, the End-Of-Body header - * should be sent and the final bit in the request will be set.) At this point, - * the reply from the server may begin to be processed. A call to - * getResponseCode() will do an implicit close on the - * OutputStream and therefore signal that the request is done. - *

Client GET Operation Flow

For GET operation, a call to - * openInputStream() or openDataInputStream() will - * signal that the request is done. (In OBEX terms, the final bit in the request - * will be set.) A call to getResponseCode() will cause an implicit - * close on the InputStream. No further data may be read at this - * point. - * @hide - */ -public interface Operation { - - /** - * Sends an ABORT message to the server. By calling this method, the - * corresponding input and output streams will be closed along with this - * object. No headers are sent in the abort request. This will end the - * operation since close() will be called by this method. - * @throws IOException if the transaction has already ended or if an OBEX - * server calls this method - */ - void abort() throws IOException; - - /** - * Returns the headers that have been received during the operation. - * Modifying the object returned has no effect on the headers that are sent - * or retrieved. - * @return the headers received during this Operation - * @throws IOException if this Operation has been closed - */ - HeaderSet getReceivedHeader() throws IOException; - - /** - * Specifies the headers that should be sent in the next OBEX message that - * is sent. - * @param headers the headers to send in the next message - * @throws IOException if this Operation has been closed or the - * transaction has ended and no further messages will be exchanged - * @throws IllegalArgumentException if headers was not created - * by a call to ServerRequestHandler.createHeaderSet() - * or ClientSession.createHeaderSet() - * @throws NullPointerException if headers if null - */ - void sendHeaders(HeaderSet headers) throws IOException; - - /** - * Returns the response code received from the server. Response codes are - * defined in the ResponseCodes class. - * @see ResponseCodes - * @return the response code retrieved from the server - * @throws IOException if an error occurred in the transport layer during - * the transaction; if this object was created by an OBEX server - */ - int getResponseCode() throws IOException; - - String getEncoding(); - - long getLength(); - - int getHeaderLength(); - - String getType(); - - InputStream openInputStream() throws IOException; - - DataInputStream openDataInputStream() throws IOException; - - OutputStream openOutputStream() throws IOException; - - DataOutputStream openDataOutputStream() throws IOException; - - void close() throws IOException; - - int getMaxPacketSize(); - - public void noBodyHeader(); -} diff --git a/obex/javax/obex/PasswordAuthentication.java b/obex/javax/obex/PasswordAuthentication.java deleted file mode 100644 index 326b1ff56a74..000000000000 --- a/obex/javax/obex/PasswordAuthentication.java +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Copyright (c) 2008-2009, Motorola, Inc. - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * - Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * - Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * - Neither the name of the Motorola, Inc. nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -package javax.obex; - -/** - * This class holds user name and password combinations. - * @hide - */ -public final class PasswordAuthentication { - - private byte[] mUserName; - - private final byte[] mPassword; - - /** - * Creates a new PasswordAuthentication with the user name and - * password provided. - * @param userName the user name to include; this may be null - * @param password the password to include in the response - * @throws NullPointerException if password is - * null - */ - public PasswordAuthentication(final byte[] userName, final byte[] password) { - if (userName != null) { - mUserName = new byte[userName.length]; - System.arraycopy(userName, 0, mUserName, 0, userName.length); - } - - mPassword = new byte[password.length]; - System.arraycopy(password, 0, mPassword, 0, password.length); - } - - /** - * Retrieves the user name that was specified in the constructor. The user - * name may be null. - * @return the user name - */ - public byte[] getUserName() { - return mUserName; - } - - /** - * Retrieves the password. - * @return the password - */ - public byte[] getPassword() { - return mPassword; - } -} diff --git a/obex/javax/obex/PrivateInputStream.java b/obex/javax/obex/PrivateInputStream.java deleted file mode 100644 index 5daee72474fc..000000000000 --- a/obex/javax/obex/PrivateInputStream.java +++ /dev/null @@ -1,181 +0,0 @@ -/* - * Copyright (c) 2008-2009, Motorola, Inc. - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * - Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * - Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * - Neither the name of the Motorola, Inc. nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -package javax.obex; - -import java.io.InputStream; -import java.io.IOException; - -/** - * This object provides an input stream to the Operation objects used in this - * package. - * @hide - */ -public final class PrivateInputStream extends InputStream { - - private BaseStream mParent; - - private byte[] mData; - - private int mIndex; - - private boolean mOpen; - - /** - * Creates an input stream for the Operation to read from - * @param p the connection this input stream is for - */ - public PrivateInputStream(BaseStream p) { - mParent = p; - mData = new byte[0]; - mIndex = 0; - mOpen = true; - } - - /** - * Returns the number of bytes that can be read (or skipped over) from this - * input stream without blocking by the next caller of a method for this - * input stream. The next caller might be the same thread or or another - * thread. - * @return the number of bytes that can be read from this input stream - * without blocking - * @throws IOException if an I/O error occurs - */ - @Override - public synchronized int available() throws IOException { - ensureOpen(); - return mData.length - mIndex; - } - - /** - * Reads the next byte of data from the input stream. The value byte is - * returned as an int in the range 0 to 255. If no byte is available because - * the end of the stream has been reached, the value -1 is returned. This - * method blocks until input data is available, the end of the stream is - * detected, or an exception is thrown. - * @return the byte read from the input stream or -1 if it reaches the end of - * stream - * @throws IOException if an I/O error occurs - */ - @Override - public synchronized int read() throws IOException { - ensureOpen(); - while (mData.length == mIndex) { - if (!mParent.continueOperation(true, true)) { - return -1; - } - } - return (mData[mIndex++] & 0xFF); - } - - @Override - public int read(byte[] b) throws IOException { - return read(b, 0, b.length); - } - - @Override - public synchronized int read(byte[] b, int offset, int length) throws IOException { - - if (b == null) { - throw new IOException("buffer is null"); - } - if ((offset | length) < 0 || length > b.length - offset) { - throw new ArrayIndexOutOfBoundsException("index outof bound"); - } - ensureOpen(); - - int currentDataLength = mData.length - mIndex; - int remainReadLength = length; - int offset1 = offset; - int result = 0; - - while (currentDataLength <= remainReadLength) { - System.arraycopy(mData, mIndex, b, offset1, currentDataLength); - mIndex += currentDataLength; - offset1 += currentDataLength; - result += currentDataLength; - remainReadLength -= currentDataLength; - - if (!mParent.continueOperation(true, true)) { - return result == 0 ? -1 : result; - } - currentDataLength = mData.length - mIndex; - } - if (remainReadLength > 0) { - System.arraycopy(mData, mIndex, b, offset1, remainReadLength); - mIndex += remainReadLength; - result += remainReadLength; - } - return result; - } - - /** - * Allows the OperationImpl thread to add body data to the - * input stream. - * @param body the data to add to the stream - * @param start the start of the body to array to copy - */ - public synchronized void writeBytes(byte[] body, int start) { - - int length = (body.length - start) + (mData.length - mIndex); - byte[] temp = new byte[length]; - - System.arraycopy(mData, mIndex, temp, 0, mData.length - mIndex); - System.arraycopy(body, start, temp, mData.length - mIndex, body.length - start); - - mData = temp; - mIndex = 0; - notifyAll(); - } - - /** - * Verifies that this stream is open - * @throws IOException if the stream is not open - */ - private void ensureOpen() throws IOException { - mParent.ensureOpen(); - if (!mOpen) { - throw new IOException("Input stream is closed"); - } - } - - /** - * Closes the input stream. If the input stream is already closed, do - * nothing. - * @throws IOException this will never happen - */ - @Override - public void close() throws IOException { - mOpen = false; - mParent.streamClosed(true); - } -} diff --git a/obex/javax/obex/PrivateOutputStream.java b/obex/javax/obex/PrivateOutputStream.java deleted file mode 100644 index 713f4ae2cff3..000000000000 --- a/obex/javax/obex/PrivateOutputStream.java +++ /dev/null @@ -1,172 +0,0 @@ -/* - * Copyright (c) 2008-2009, Motorola, Inc. - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * - Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * - Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * - Neither the name of the Motorola, Inc. nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -package javax.obex; - -import java.io.IOException; -import java.io.OutputStream; -import java.io.ByteArrayOutputStream; - -/** - * This object provides an output stream to the Operation objects used in this - * package. - * @hide - */ -public final class PrivateOutputStream extends OutputStream { - - private BaseStream mParent; - - private ByteArrayOutputStream mArray; - - private boolean mOpen; - - private int mMaxPacketSize; - - /** - * Creates an empty PrivateOutputStream to write to. - * @param p the connection that this stream runs over - */ - public PrivateOutputStream(BaseStream p, int maxSize) { - mParent = p; - mArray = new ByteArrayOutputStream(); - mMaxPacketSize = maxSize; - mOpen = true; - } - - /** - * Determines how many bytes have been written to the output stream. - * @return the number of bytes written to the output stream - */ - public int size() { - return mArray.size(); - } - - /** - * Writes the specified byte to this output stream. The general contract for - * write is that one byte is written to the output stream. The byte to be - * written is the eight low-order bits of the argument b. The 24 high-order - * bits of b are ignored. - * @param b the byte to write - * @throws IOException if an I/O error occurs - */ - @Override - public synchronized void write(int b) throws IOException { - ensureOpen(); - mParent.ensureNotDone(); - mArray.write(b); - if (mArray.size() == mMaxPacketSize) { - mParent.continueOperation(true, false); - } - } - - @Override - public void write(byte[] buffer) throws IOException { - write(buffer, 0, buffer.length); - } - - @Override - public synchronized void write(byte[] buffer, int offset, int count) throws IOException { - int offset1 = offset; - int remainLength = count; - - if (buffer == null) { - throw new IOException("buffer is null"); - } - if ((offset | count) < 0 || count > buffer.length - offset) { - throw new IndexOutOfBoundsException("index outof bound"); - } - - ensureOpen(); - mParent.ensureNotDone(); - while ((mArray.size() + remainLength) >= mMaxPacketSize) { - int bufferLeft = mMaxPacketSize - mArray.size(); - mArray.write(buffer, offset1, bufferLeft); - offset1 += bufferLeft; - remainLength -= bufferLeft; - mParent.continueOperation(true, false); - } - if (remainLength > 0) { - mArray.write(buffer, offset1, remainLength); - } - } - - /** - * Reads the bytes that have been written to this stream. - * @param size the size of the array to return - * @return the byte array that is written - */ - public synchronized byte[] readBytes(int size) { - if (mArray.size() > 0) { - byte[] temp = mArray.toByteArray(); - mArray.reset(); - byte[] result = new byte[size]; - System.arraycopy(temp, 0, result, 0, size); - if (temp.length != size) { - mArray.write(temp, size, temp.length - size); - } - return result; - } else { - return null; - } - } - - /** - * Verifies that this stream is open - * @throws IOException if the stream is not open - */ - private void ensureOpen() throws IOException { - mParent.ensureOpen(); - if (!mOpen) { - throw new IOException("Output stream is closed"); - } - } - - /** - * Closes the output stream. If the input stream is already closed, do - * nothing. - * @throws IOException this will never happen - */ - @Override - public void close() throws IOException { - mOpen = false; - mParent.streamClosed(false); - } - - /** - * Determines if the connection is closed - * @return true if the connection is closed; false - * if the connection is open - */ - public boolean isClosed() { - return !mOpen; - } -} diff --git a/obex/javax/obex/ResponseCodes.java b/obex/javax/obex/ResponseCodes.java deleted file mode 100644 index a2b9a37b4af1..000000000000 --- a/obex/javax/obex/ResponseCodes.java +++ /dev/null @@ -1,326 +0,0 @@ -/* - * Copyright (c) 2008-2009, Motorola, Inc. - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * - Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * - Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * - Neither the name of the Motorola, Inc. nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -package javax.obex; - -/** - * The ResponseCodes class contains the list of valid response - * codes a server may send to a client. - *

- * IMPORTANT NOTE - *

- * The values in this interface represent the values defined in the IrOBEX - * specification, which is different with the HTTP specification. - *

- * OBEX_DATABASE_FULL and OBEX_DATABASE_LOCKED require - * further description since they are not defined in HTTP. The server will send - * an OBEX_DATABASE_FULL message when the client requests that - * something be placed into a database but the database is full (cannot take - * more data). OBEX_DATABASE_LOCKED will be returned when the - * client wishes to access a database, database table, or database record that - * has been locked. - * @hide - */ -public final class ResponseCodes { - - /** - * Defines the OBEX CONTINUE response code. - *

- * The value of OBEX_HTTP_CONTINUE is 0x90 (144). - */ - public static final int OBEX_HTTP_CONTINUE = 0x90; - - /** - * Defines the OBEX SUCCESS response code. - *

- * The value of OBEX_HTTP_OK is 0xA0 (160). - */ - public static final int OBEX_HTTP_OK = 0xA0; - - /** - * Defines the OBEX CREATED response code. - *

- * The value of OBEX_HTTP_CREATED is 0xA1 (161). - */ - public static final int OBEX_HTTP_CREATED = 0xA1; - - /** - * Defines the OBEX ACCEPTED response code. - *

- * The value of OBEX_HTTP_ACCEPTED is 0xA2 (162). - */ - public static final int OBEX_HTTP_ACCEPTED = 0xA2; - - /** - * Defines the OBEX NON-AUTHORITATIVE INFORMATION response code. - *

- * The value of OBEX_HTTP_NOT_AUTHORITATIVE is 0xA3 (163). - */ - public static final int OBEX_HTTP_NOT_AUTHORITATIVE = 0xA3; - - /** - * Defines the OBEX NO CONTENT response code. - *

- * The value of OBEX_HTTP_NO_CONTENT is 0xA4 (164). - */ - public static final int OBEX_HTTP_NO_CONTENT = 0xA4; - - /** - * Defines the OBEX RESET CONTENT response code. - *

- * The value of OBEX_HTTP_RESET is 0xA5 (165). - */ - public static final int OBEX_HTTP_RESET = 0xA5; - - /** - * Defines the OBEX PARTIAL CONTENT response code. - *

- * The value of OBEX_HTTP_PARTIAL is 0xA6 (166). - */ - public static final int OBEX_HTTP_PARTIAL = 0xA6; - - /** - * Defines the OBEX MULTIPLE_CHOICES response code. - *

- * The value of OBEX_HTTP_MULT_CHOICE is 0xB0 (176). - */ - public static final int OBEX_HTTP_MULT_CHOICE = 0xB0; - - /** - * Defines the OBEX MOVED PERMANENTLY response code. - *

- * The value of OBEX_HTTP_MOVED_PERM is 0xB1 (177). - */ - public static final int OBEX_HTTP_MOVED_PERM = 0xB1; - - /** - * Defines the OBEX MOVED TEMPORARILY response code. - *

- * The value of OBEX_HTTP_MOVED_TEMP is 0xB2 (178). - */ - public static final int OBEX_HTTP_MOVED_TEMP = 0xB2; - - /** - * Defines the OBEX SEE OTHER response code. - *

- * The value of OBEX_HTTP_SEE_OTHER is 0xB3 (179). - */ - public static final int OBEX_HTTP_SEE_OTHER = 0xB3; - - /** - * Defines the OBEX NOT MODIFIED response code. - *

- * The value of OBEX_HTTP_NOT_MODIFIED is 0xB4 (180). - */ - public static final int OBEX_HTTP_NOT_MODIFIED = 0xB4; - - /** - * Defines the OBEX USE PROXY response code. - *

- * The value of OBEX_HTTP_USE_PROXY is 0xB5 (181). - */ - public static final int OBEX_HTTP_USE_PROXY = 0xB5; - - /** - * Defines the OBEX BAD REQUEST response code. - *

- * The value of OBEX_HTTP_BAD_REQUEST is 0xC0 (192). - */ - public static final int OBEX_HTTP_BAD_REQUEST = 0xC0; - - /** - * Defines the OBEX UNAUTHORIZED response code. - *

- * The value of OBEX_HTTP_UNAUTHORIZED is 0xC1 (193). - */ - public static final int OBEX_HTTP_UNAUTHORIZED = 0xC1; - - /** - * Defines the OBEX PAYMENT REQUIRED response code. - *

- * The value of OBEX_HTTP_PAYMENT_REQUIRED is 0xC2 (194). - */ - public static final int OBEX_HTTP_PAYMENT_REQUIRED = 0xC2; - - /** - * Defines the OBEX FORBIDDEN response code. - *

- * The value of OBEX_HTTP_FORBIDDEN is 0xC3 (195). - */ - public static final int OBEX_HTTP_FORBIDDEN = 0xC3; - - /** - * Defines the OBEX NOT FOUND response code. - *

- * The value of OBEX_HTTP_NOT_FOUND is 0xC4 (196). - */ - public static final int OBEX_HTTP_NOT_FOUND = 0xC4; - - /** - * Defines the OBEX METHOD NOT ALLOWED response code. - *

- * The value of OBEX_HTTP_BAD_METHOD is 0xC5 (197). - */ - public static final int OBEX_HTTP_BAD_METHOD = 0xC5; - - /** - * Defines the OBEX NOT ACCEPTABLE response code. - *

- * The value of OBEX_HTTP_NOT_ACCEPTABLE is 0xC6 (198). - */ - public static final int OBEX_HTTP_NOT_ACCEPTABLE = 0xC6; - - /** - * Defines the OBEX PROXY AUTHENTICATION REQUIRED response code. - *

- * The value of OBEX_HTTP_PROXY_AUTH is 0xC7 (199). - */ - public static final int OBEX_HTTP_PROXY_AUTH = 0xC7; - - /** - * Defines the OBEX REQUEST TIME OUT response code. - *

- * The value of OBEX_HTTP_TIMEOUT is 0xC8 (200). - */ - public static final int OBEX_HTTP_TIMEOUT = 0xC8; - - /** - * Defines the OBEX METHOD CONFLICT response code. - *

- * The value of OBEX_HTTP_CONFLICT is 0xC9 (201). - */ - public static final int OBEX_HTTP_CONFLICT = 0xC9; - - /** - * Defines the OBEX METHOD GONE response code. - *

- * The value of OBEX_HTTP_GONE is 0xCA (202). - */ - public static final int OBEX_HTTP_GONE = 0xCA; - - /** - * Defines the OBEX METHOD LENGTH REQUIRED response code. - *

- * The value of OBEX_HTTP_LENGTH_REQUIRED is 0xCB (203). - */ - public static final int OBEX_HTTP_LENGTH_REQUIRED = 0xCB; - - /** - * Defines the OBEX PRECONDITION FAILED response code. - *

- * The value of OBEX_HTTP_PRECON_FAILED is 0xCC (204). - */ - public static final int OBEX_HTTP_PRECON_FAILED = 0xCC; - - /** - * Defines the OBEX REQUESTED ENTITY TOO LARGE response code. - *

- * The value of OBEX_HTTP_ENTITY_TOO_LARGE is 0xCD (205). - */ - public static final int OBEX_HTTP_ENTITY_TOO_LARGE = 0xCD; - - /** - * Defines the OBEX REQUESTED URL TOO LARGE response code. - *

- * The value of OBEX_HTTP_REQ_TOO_LARGE is 0xCE (206). - */ - public static final int OBEX_HTTP_REQ_TOO_LARGE = 0xCE; - - /** - * Defines the OBEX UNSUPPORTED MEDIA TYPE response code. - *

- * The value of OBEX_HTTP_UNSUPPORTED_TYPE is 0xCF (207). - */ - public static final int OBEX_HTTP_UNSUPPORTED_TYPE = 0xCF; - - /** - * Defines the OBEX INTERNAL SERVER ERROR response code. - *

- * The value of OBEX_HTTP_INTERNAL_ERROR is 0xD0 (208). - */ - public static final int OBEX_HTTP_INTERNAL_ERROR = 0xD0; - - /** - * Defines the OBEX NOT IMPLEMENTED response code. - *

- * The value of OBEX_HTTP_NOT_IMPLEMENTED is 0xD1 (209). - */ - public static final int OBEX_HTTP_NOT_IMPLEMENTED = 0xD1; - - /** - * Defines the OBEX BAD GATEWAY response code. - *

- * The value of OBEX_HTTP_BAD_GATEWAY is 0xD2 (210). - */ - public static final int OBEX_HTTP_BAD_GATEWAY = 0xD2; - - /** - * Defines the OBEX SERVICE UNAVAILABLE response code. - *

- * The value of OBEX_HTTP_UNAVAILABLE is 0xD3 (211). - */ - public static final int OBEX_HTTP_UNAVAILABLE = 0xD3; - - /** - * Defines the OBEX GATEWAY TIMEOUT response code. - *

- * The value of OBEX_HTTP_GATEWAY_TIMEOUT is 0xD4 (212). - */ - public static final int OBEX_HTTP_GATEWAY_TIMEOUT = 0xD4; - - /** - * Defines the OBEX HTTP VERSION NOT SUPPORTED response code. - *

- * The value of OBEX_HTTP_VERSION is 0xD5 (213). - */ - public static final int OBEX_HTTP_VERSION = 0xD5; - - /** - * Defines the OBEX DATABASE FULL response code. - *

- * The value of OBEX_DATABASE_FULL is 0xE0 (224). - */ - public static final int OBEX_DATABASE_FULL = 0xE0; - - /** - * Defines the OBEX DATABASE LOCKED response code. - *

- * The value of OBEX_DATABASE_LOCKED is 0xE1 (225). - */ - public static final int OBEX_DATABASE_LOCKED = 0xE1; - - /** - * Constructor does nothing. - */ - private ResponseCodes() { - } -} diff --git a/obex/javax/obex/ServerOperation.java b/obex/javax/obex/ServerOperation.java deleted file mode 100644 index 15ea36789e2c..000000000000 --- a/obex/javax/obex/ServerOperation.java +++ /dev/null @@ -1,861 +0,0 @@ -/* Copyright (c) 2015 The Android Open Source Project - * Copyright (C) 2015 Samsung LSI - * Copyright (c) 2008-2009, Motorola, Inc. - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * - Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * - Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * - Neither the name of the Motorola, Inc. nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -package javax.obex; - -import java.io.IOException; -import java.io.InputStream; -import java.io.DataInputStream; -import java.io.OutputStream; -import java.io.DataOutputStream; -import java.io.ByteArrayOutputStream; - -import android.util.Log; - -/** - * This class implements the Operation interface for server side connections. - *

- * Request Codes There are four different request codes that - * are in this class. 0x02 is a PUT request that signals that the request is not - * complete and requires an additional OBEX packet. 0x82 is a PUT request that - * says that request is complete. In this case, the server can begin sending the - * response. The 0x03 is a GET request that signals that the request is not - * finished. When the server receives a 0x83, the client is signaling the server - * that it is done with its request. TODO: Extend the ClientOperation and reuse - * the methods defined TODO: in that class. - * @hide - */ -public final class ServerOperation implements Operation, BaseStream { - - private static final String TAG = "ServerOperation"; - - private static final boolean V = ObexHelper.VDBG; // Verbose debugging - - public boolean isAborted; - - public HeaderSet requestHeader; - - public HeaderSet replyHeader; - - public boolean finalBitSet; - - private InputStream mInput; - - private ServerSession mParent; - - private int mMaxPacketLength; - - private int mResponseSize; - - private boolean mClosed; - - private boolean mGetOperation; - - private PrivateInputStream mPrivateInput; - - private PrivateOutputStream mPrivateOutput; - - private ObexTransport mTransport; - - private boolean mPrivateOutputOpen; - - private String mExceptionString; - - private ServerRequestHandler mListener; - - private boolean mRequestFinished; - - private boolean mHasBody; - - private boolean mSendBodyHeader = true; - // Assume SRM disabled - needs to be explicit - // enabled by client - private boolean mSrmEnabled = false; - // A latch - when triggered, there is not way back ;-) - private boolean mSrmActive = false; - // Set to true when a SRM enable response have been send - private boolean mSrmResponseSent = false; - // keep waiting until final-bit is received in request - // to handle the case where the SRM enable header is in - // a different OBEX packet than the SRMP header. - private boolean mSrmWaitingForRemote = true; - // Why should we wait? - currently not exposed to apps. - private boolean mSrmLocalWait = false; - - /** - * Creates new ServerOperation - * @param p the parent that created this object - * @param in the input stream to read from - * @param out the output stream to write to - * @param request the initial request that was received from the client - * @param maxSize the max packet size that the client will accept - * @param listen the listener that is responding to the request - * @throws IOException if an IO error occurs - */ - public ServerOperation(ServerSession p, InputStream in, int request, int maxSize, - ServerRequestHandler listen) throws IOException { - - isAborted = false; - mParent = p; - mInput = in; - mMaxPacketLength = maxSize; - mClosed = false; - requestHeader = new HeaderSet(); - replyHeader = new HeaderSet(); - mPrivateInput = new PrivateInputStream(this); - mResponseSize = 3; - mListener = listen; - mRequestFinished = false; - mPrivateOutputOpen = false; - mHasBody = false; - ObexPacket packet; - mTransport = p.getTransport(); - - /* - * Determine if this is a PUT request - */ - if ((request == ObexHelper.OBEX_OPCODE_PUT) || - (request == ObexHelper.OBEX_OPCODE_PUT_FINAL)) { - /* - * It is a PUT request. - */ - mGetOperation = false; - - /* - * Determine if the final bit is set - */ - if ((request & ObexHelper.OBEX_OPCODE_FINAL_BIT_MASK) == 0) { - finalBitSet = false; - } else { - finalBitSet = true; - mRequestFinished = true; - } - } else if ((request == ObexHelper.OBEX_OPCODE_GET) || - (request == ObexHelper.OBEX_OPCODE_GET_FINAL)) { - /* - * It is a GET request. - */ - mGetOperation = true; - - // For Get request, final bit set is decided by server side logic - finalBitSet = false; - - if (request == ObexHelper.OBEX_OPCODE_GET_FINAL) { - mRequestFinished = true; - } - } else { - throw new IOException("ServerOperation can not handle such request"); - } - - packet = ObexPacket.read(request, mInput); - - /* - * Determine if the packet length is larger than this device can receive - */ - if (packet.mLength > ObexHelper.getMaxRxPacketSize(mTransport)) { - mParent.sendResponse(ResponseCodes.OBEX_HTTP_REQ_TOO_LARGE, null); - throw new IOException("Packet received was too large. Length: " - + packet.mLength + " maxLength: " + ObexHelper.getMaxRxPacketSize(mTransport)); - } - - /* - * Determine if any headers were sent in the initial request - */ - if (packet.mLength > 3) { - if(!handleObexPacket(packet)) { - return; - } - /* Don't Pre-Send continue when Remote requested for SRM - * Let the Application confirm. - */ - if (V) Log.v(TAG, "Get App confirmation if SRM ENABLED case: " + mSrmEnabled - + " not hasBody case: " + mHasBody); - if (!mHasBody && !mSrmEnabled) { - while ((!mGetOperation) && (!finalBitSet)) { - sendReply(ResponseCodes.OBEX_HTTP_CONTINUE); - if (mPrivateInput.available() > 0) { - break; - } - } - } - } - /* Don't Pre-Send continue when Remote requested for SRM - * Let the Application confirm. - */ - if (V) Log.v(TAG, "Get App confirmation if SRM ENABLED case: " + mSrmEnabled - + " not finalPacket: " + finalBitSet + " not GETOp Case: " + mGetOperation); - while ((!mSrmEnabled) && (!mGetOperation) && (!finalBitSet) - && (mPrivateInput.available() == 0)) { - sendReply(ResponseCodes.OBEX_HTTP_CONTINUE); - if (mPrivateInput.available() > 0) { - break; - } - } - - // wait for get request finished !!!! - while (mGetOperation && !mRequestFinished) { - sendReply(ResponseCodes.OBEX_HTTP_CONTINUE); - } - } - - /** - * Parse headers and update member variables - * @param packet the received obex packet - * @return false for failing authentication - and a OBEX_HTTP_UNAUTHORIZED - * response have been send. Else true. - * @throws IOException - */ - private boolean handleObexPacket(ObexPacket packet) throws IOException { - byte[] body = updateRequestHeaders(packet); - - if (body != null) { - mHasBody = true; - } - if (mListener.getConnectionId() != -1 && requestHeader.mConnectionID != null) { - mListener.setConnectionId(ObexHelper - .convertToLong(requestHeader.mConnectionID)); - } else { - mListener.setConnectionId(1); - } - - if (requestHeader.mAuthResp != null) { - if (!mParent.handleAuthResp(requestHeader.mAuthResp)) { - mExceptionString = "Authentication Failed"; - mParent.sendResponse(ResponseCodes.OBEX_HTTP_UNAUTHORIZED, null); - mClosed = true; - requestHeader.mAuthResp = null; - return false; - } - requestHeader.mAuthResp = null; - } - - if (requestHeader.mAuthChall != null) { - mParent.handleAuthChall(requestHeader); - // send the auhtResp to the client - replyHeader.mAuthResp = new byte[requestHeader.mAuthResp.length]; - System.arraycopy(requestHeader.mAuthResp, 0, replyHeader.mAuthResp, 0, - replyHeader.mAuthResp.length); - requestHeader.mAuthResp = null; - requestHeader.mAuthChall = null; - } - - if (body != null) { - mPrivateInput.writeBytes(body, 1); - } - return true; - } - - /** - * Update the request header set, and sniff on SRM headers to update local state. - * @param data the OBEX packet data - * @return any bytes in a body/end-of-body header returned by {@link ObexHelper.updateHeaderSet} - * @throws IOException - */ - private byte[] updateRequestHeaders(ObexPacket packet) throws IOException { - byte[] body = null; - if (packet.mPayload != null) { - body = ObexHelper.updateHeaderSet(requestHeader, packet.mPayload); - } - Byte srmMode = (Byte)requestHeader.getHeader(HeaderSet.SINGLE_RESPONSE_MODE); - if(mTransport.isSrmSupported() && srmMode != null - && srmMode == ObexHelper.OBEX_SRM_ENABLE) { - mSrmEnabled = true; - if(V) Log.d(TAG,"SRM is now ENABLED (but not active) for this operation"); - } - checkForSrmWait(packet.mHeaderId); - if((!mSrmWaitingForRemote) && (mSrmEnabled)) { - if(V) Log.d(TAG,"SRM is now ACTIVE for this operation"); - mSrmActive = true; - } - return body; - } - - /** - * Call this only when a complete request have been received. - * (This is not optimal, but the current design is not really suited to - * the way SRM is specified.) - */ - private void checkForSrmWait(int headerId){ - if (mSrmEnabled && (headerId == ObexHelper.OBEX_OPCODE_GET - || headerId == ObexHelper.OBEX_OPCODE_GET_FINAL - || headerId == ObexHelper.OBEX_OPCODE_PUT)) { - try { - mSrmWaitingForRemote = false; - Byte srmp = (Byte)requestHeader.getHeader(HeaderSet.SINGLE_RESPONSE_MODE_PARAMETER); - if(srmp != null && srmp == ObexHelper.OBEX_SRMP_WAIT) { - mSrmWaitingForRemote = true; - // Clear the wait header, as the absents of the header when the final bit is set - // indicates don't wait. - requestHeader.setHeader(HeaderSet.SINGLE_RESPONSE_MODE_PARAMETER, null); - } - } catch (IOException e) {if(V){Log.w(TAG,"Exception while extracting header",e);}} - } - } - - public boolean isValidBody() { - return mHasBody; - } - - /** - * Determines if the operation should continue or should wait. If it should - * continue, this method will continue the operation. - * @param sendEmpty if true then this will continue the - * operation even if no headers will be sent; if false - * then this method will only continue the operation if there are - * headers to send - * @param inStream iftrue the stream is input stream, otherwise - * output stream - * @return true if the operation was completed; - * false if no operation took place - */ - public synchronized boolean continueOperation(boolean sendEmpty, boolean inStream) - throws IOException { - if (!mGetOperation) { - if (!finalBitSet) { - if (sendEmpty) { - sendReply(ResponseCodes.OBEX_HTTP_CONTINUE); - return true; - } else { - if ((mResponseSize > 3) || (mPrivateOutput.size() > 0)) { - sendReply(ResponseCodes.OBEX_HTTP_CONTINUE); - return true; - } else { - return false; - } - } - } else { - return false; - } - } else { - sendReply(ResponseCodes.OBEX_HTTP_CONTINUE); - return true; - } - } - - /** - * Sends a reply to the client. If the reply is a OBEX_HTTP_CONTINUE, it - * will wait for a response from the client before ending unless SRM is active. - * @param type the response code to send back to the client - * @return true if the final bit was not set on the reply; - * false if no reply was received because the operation - * ended, an abort was received, the final bit was set in the - * reply or SRM is active. - * @throws IOException if an IO error occurs - */ - public synchronized boolean sendReply(int type) throws IOException { - ByteArrayOutputStream out = new ByteArrayOutputStream(); - boolean skipSend = false; - boolean skipReceive = false; - boolean srmRespSendPending = false; - - long id = mListener.getConnectionId(); - if (id == -1) { - replyHeader.mConnectionID = null; - } else { - replyHeader.mConnectionID = ObexHelper.convertToByteArray(id); - } - - if(mSrmEnabled && !mSrmResponseSent) { - // As we are not ensured that the SRM enable is in the first OBEX packet - // We must check for each reply. - if(V)Log.v(TAG, "mSrmEnabled==true, sending SRM enable response."); - replyHeader.setHeader(HeaderSet.SINGLE_RESPONSE_MODE, (byte)ObexHelper.OBEX_SRM_ENABLE); - srmRespSendPending = true; - } - - if(mSrmEnabled && !mGetOperation && mSrmLocalWait) { - replyHeader.setHeader(HeaderSet.SINGLE_RESPONSE_MODE, (byte)ObexHelper.OBEX_SRMP_WAIT); - } - - byte[] headerArray = ObexHelper.createHeader(replyHeader, true); // This clears the headers - int bodyLength = -1; - int orginalBodyLength = -1; - - if (mPrivateOutput != null) { - bodyLength = mPrivateOutput.size(); - orginalBodyLength = bodyLength; - } - - if ((ObexHelper.BASE_PACKET_LENGTH + headerArray.length) > mMaxPacketLength) { - - int end = 0; - int start = 0; - - while (end != headerArray.length) { - end = ObexHelper.findHeaderEnd(headerArray, start, mMaxPacketLength - - ObexHelper.BASE_PACKET_LENGTH); - if (end == -1) { - - mClosed = true; - - if (mPrivateInput != null) { - mPrivateInput.close(); - } - - if (mPrivateOutput != null) { - mPrivateOutput.close(); - } - mParent.sendResponse(ResponseCodes.OBEX_HTTP_INTERNAL_ERROR, null); - throw new IOException("OBEX Packet exceeds max packet size"); - } - byte[] sendHeader = new byte[end - start]; - System.arraycopy(headerArray, start, sendHeader, 0, sendHeader.length); - - mParent.sendResponse(type, sendHeader); - start = end; - } - - if (bodyLength > 0) { - return true; - } else { - return false; - } - - } else { - out.write(headerArray); - } - - // For Get operation: if response code is OBEX_HTTP_OK, then this is the - // last packet; so set finalBitSet to true. - if (mGetOperation && type == ResponseCodes.OBEX_HTTP_OK) { - finalBitSet = true; - } - - if(mSrmActive) { - if(!mGetOperation && type == ResponseCodes.OBEX_HTTP_CONTINUE && - mSrmResponseSent == true) { - // we are in the middle of a SRM PUT operation, don't send a continue. - skipSend = true; - } else if(mGetOperation && mRequestFinished == false && mSrmResponseSent == true) { - // We are still receiving the get request, receive, but don't send continue. - skipSend = true; - } else if(mGetOperation && mRequestFinished == true) { - // All done receiving the GET request, send data to the client, without - // expecting a continue. - skipReceive = true; - } - if(V)Log.v(TAG, "type==" + type + " skipSend==" + skipSend - + " skipReceive==" + skipReceive); - } - if(srmRespSendPending) { - if(V)Log.v(TAG, - "SRM Enabled (srmRespSendPending == true)- sending SRM Enable response"); - mSrmResponseSent = true; - } - - if ((finalBitSet) || (headerArray.length < (mMaxPacketLength - 20))) { - if (bodyLength > 0) { - /* - * Determine if I can send the whole body or just part of - * the body. Remember that there is the 3 bytes for the - * response message and 3 bytes for the header ID and length - */ - if (bodyLength > (mMaxPacketLength - headerArray.length - 6)) { - bodyLength = mMaxPacketLength - headerArray.length - 6; - } - - byte[] body = mPrivateOutput.readBytes(bodyLength); - - /* - * Since this is a put request if the final bit is set or - * the output stream is closed we need to send the 0x49 - * (End of Body) otherwise, we need to send 0x48 (Body) - */ - if ((finalBitSet) || (mPrivateOutput.isClosed())) { - if(mSendBodyHeader == true) { - out.write(0x49); - bodyLength += 3; - out.write((byte)(bodyLength >> 8)); - out.write((byte)bodyLength); - out.write(body); - } - } else { - if(mSendBodyHeader == true) { - out.write(0x48); - bodyLength += 3; - out.write((byte)(bodyLength >> 8)); - out.write((byte)bodyLength); - out.write(body); - } - } - - } - } - - if ((finalBitSet) && (type == ResponseCodes.OBEX_HTTP_OK) && (orginalBodyLength <= 0)) { - if(mSendBodyHeader) { - out.write(0x49); - orginalBodyLength = 3; - out.write((byte)(orginalBodyLength >> 8)); - out.write((byte)orginalBodyLength); - } - } - - if(skipSend == false) { - mResponseSize = 3; - mParent.sendResponse(type, out.toByteArray()); - } - - if (type == ResponseCodes.OBEX_HTTP_CONTINUE) { - - if(mGetOperation && skipReceive) { - // Here we need to check for and handle abort (throw an exception). - // Any other signal received should be discarded silently (only on server side) - checkSrmRemoteAbort(); - } else { - // Receive and handle data (only send reply if !skipSend) - // Read a complete OBEX Packet - ObexPacket packet = ObexPacket.read(mInput); - - int headerId = packet.mHeaderId; - if ((headerId != ObexHelper.OBEX_OPCODE_PUT) - && (headerId != ObexHelper.OBEX_OPCODE_PUT_FINAL) - && (headerId != ObexHelper.OBEX_OPCODE_GET) - && (headerId != ObexHelper.OBEX_OPCODE_GET_FINAL)) { - - /* - * Determine if an ABORT was sent as the reply - */ - if (headerId == ObexHelper.OBEX_OPCODE_ABORT) { - handleRemoteAbort(); - } else { - // TODO:shall we send this if it occurs during SRM? Errata on the subject - mParent.sendResponse(ResponseCodes.OBEX_HTTP_BAD_REQUEST, null); - mClosed = true; - mExceptionString = "Bad Request Received"; - throw new IOException("Bad Request Received"); - } - } else { - - if ((headerId == ObexHelper.OBEX_OPCODE_PUT_FINAL)) { - finalBitSet = true; - } else if (headerId == ObexHelper.OBEX_OPCODE_GET_FINAL) { - mRequestFinished = true; - } - - /* - * Determine if the packet length is larger than the negotiated packet size - */ - if (packet.mLength > ObexHelper.getMaxRxPacketSize(mTransport)) { - mParent.sendResponse(ResponseCodes.OBEX_HTTP_REQ_TOO_LARGE, null); - throw new IOException("Packet received was too large"); - } - - /* - * Determine if any headers were sent in the initial request - */ - if (packet.mLength > 3 || (mSrmEnabled && packet.mLength == 3)) { - if(handleObexPacket(packet) == false) { - return false; - } - } - } - - } - return true; - } else { - return false; - } - } - - /** - * This method will look for an abort from the peer during a SRM transfer. - * The function will not block if no data has been received from the remote device. - * If data have been received, the function will block while reading the incoming - * OBEX package. - * An Abort request will be handled, and cause an IOException("Abort Received"). - * Other messages will be discarded silently as per GOEP specification. - * @throws IOException if an abort request have been received. - * TODO: I think this is an error in the specification. If we discard other messages, - * the peer device will most likely stall, as it will not receive the expected - * response for the message... - * I'm not sure how to understand "Receipt of invalid or unexpected SRM or SRMP - * header values shall be ignored by the receiving device." - * If any signal is received during an active SRM transfer it is unexpected regardless - * whether or not it contains SRM/SRMP headers... - */ - private void checkSrmRemoteAbort() throws IOException { - if(mInput.available() > 0) { - ObexPacket packet = ObexPacket.read(mInput); - /* - * Determine if an ABORT was sent as the reply - */ - if (packet.mHeaderId == ObexHelper.OBEX_OPCODE_ABORT) { - handleRemoteAbort(); - } else { - // TODO: should we throw an exception here anyway? - don't see how to - // ignore SRM/SRMP headers without ignoring the complete signal - // (in this particular case). - Log.w(TAG, "Received unexpected request from client - discarding...\n" - + " headerId: " + packet.mHeaderId + " length: " + packet.mLength); - } - } - } - - private void handleRemoteAbort() throws IOException { - /* TODO: To increase the speed of the abort operation in SRM, we need - * to be able to flush the L2CAP queue for the PSM in use. - * This could be implemented by introducing a control - * message to be send over the socket, that in the abort case - * could carry a flush command. */ - mParent.sendResponse(ResponseCodes.OBEX_HTTP_OK, null); - mClosed = true; - isAborted = true; - mExceptionString = "Abort Received"; - throw new IOException("Abort Received"); - } - - /** - * Sends an ABORT message to the server. By calling this method, the - * corresponding input and output streams will be closed along with this - * object. - * @throws IOException if the transaction has already ended or if an OBEX - * server called this method - */ - public void abort() throws IOException { - throw new IOException("Called from a server"); - } - - /** - * Returns the headers that have been received during the operation. - * Modifying the object returned has no effect on the headers that are sent - * or retrieved. - * @return the headers received during this Operation - * @throws IOException if this Operation has been closed - */ - public HeaderSet getReceivedHeader() throws IOException { - ensureOpen(); - return requestHeader; - } - - /** - * Specifies the headers that should be sent in the next OBEX message that - * is sent. - * @param headers the headers to send in the next message - * @throws IOException if this Operation has been closed or the - * transaction has ended and no further messages will be exchanged - * @throws IllegalArgumentException if headers was not created - * by a call to ServerRequestHandler.createHeaderSet() - */ - public void sendHeaders(HeaderSet headers) throws IOException { - ensureOpen(); - - if (headers == null) { - throw new IOException("Headers may not be null"); - } - - int[] headerList = headers.getHeaderList(); - if (headerList != null) { - for (int i = 0; i < headerList.length; i++) { - replyHeader.setHeader(headerList[i], headers.getHeader(headerList[i])); - } - - } - } - - /** - * Retrieves the response code retrieved from the server. Response codes are - * defined in the ResponseCodes interface. - * @return the response code retrieved from the server - * @throws IOException if an error occurred in the transport layer during - * the transaction; if this method is called on a - * HeaderSet object created by calling - * createHeaderSet in a ClientSession - * object; if this is called from a server - */ - public int getResponseCode() throws IOException { - throw new IOException("Called from a server"); - } - - /** - * Always returns null - * @return null - */ - public String getEncoding() { - return null; - } - - /** - * Returns the type of content that the resource connected to is providing. - * E.g. if the connection is via HTTP, then the value of the content-type - * header field is returned. - * @return the content type of the resource that the URL references, or - * null if not known - */ - public String getType() { - try { - return (String)requestHeader.getHeader(HeaderSet.TYPE); - } catch (IOException e) { - return null; - } - } - - /** - * Returns the length of the content which is being provided. E.g. if the - * connection is via HTTP, then the value of the content-length header field - * is returned. - * @return the content length of the resource that this connection's URL - * references, or -1 if the content length is not known - */ - public long getLength() { - try { - Long temp = (Long)requestHeader.getHeader(HeaderSet.LENGTH); - - if (temp == null) { - return -1; - } else { - return temp.longValue(); - } - } catch (IOException e) { - return -1; - } - } - - public int getMaxPacketSize() { - return mMaxPacketLength - 6 - getHeaderLength(); - } - - public int getHeaderLength() { - long id = mListener.getConnectionId(); - if (id == -1) { - replyHeader.mConnectionID = null; - } else { - replyHeader.mConnectionID = ObexHelper.convertToByteArray(id); - } - - byte[] headerArray = ObexHelper.createHeader(replyHeader, false); - - return headerArray.length; - } - - /** - * Open and return an input stream for a connection. - * @return an input stream - * @throws IOException if an I/O error occurs - */ - public InputStream openInputStream() throws IOException { - ensureOpen(); - return mPrivateInput; - } - - /** - * Open and return a data input stream for a connection. - * @return an input stream - * @throws IOException if an I/O error occurs - */ - public DataInputStream openDataInputStream() throws IOException { - return new DataInputStream(openInputStream()); - } - - /** - * Open and return an output stream for a connection. - * @return an output stream - * @throws IOException if an I/O error occurs - */ - public OutputStream openOutputStream() throws IOException { - ensureOpen(); - - if (mPrivateOutputOpen) { - throw new IOException("no more input streams available, stream already opened"); - } - - if (!mRequestFinished) { - throw new IOException("no output streams available ,request not finished"); - } - - if (mPrivateOutput == null) { - mPrivateOutput = new PrivateOutputStream(this, getMaxPacketSize()); - } - mPrivateOutputOpen = true; - return mPrivateOutput; - } - - /** - * Open and return a data output stream for a connection. - * @return an output stream - * @throws IOException if an I/O error occurs - */ - public DataOutputStream openDataOutputStream() throws IOException { - return new DataOutputStream(openOutputStream()); - } - - /** - * Closes the connection and ends the transaction - * @throws IOException if the operation has already ended or is closed - */ - public void close() throws IOException { - ensureOpen(); - mClosed = true; - } - - /** - * Verifies that the connection is open and no exceptions should be thrown. - * @throws IOException if an exception needs to be thrown - */ - public void ensureOpen() throws IOException { - if (mExceptionString != null) { - throw new IOException(mExceptionString); - } - if (mClosed) { - throw new IOException("Operation has already ended"); - } - } - - /** - * Verifies that additional information may be sent. In other words, the - * operation is not done. - *

- * Included to implement the BaseStream interface only. It does not do - * anything on the server side since the operation of the Operation object - * is not done until after the handler returns from its method. - * @throws IOException if the operation is completed - */ - public void ensureNotDone() throws IOException { - } - - /** - * Called when the output or input stream is closed. It does not do anything - * on the server side since the operation of the Operation object is not - * done until after the handler returns from its method. - * @param inStream true if the input stream is closed; - * false if the output stream is closed - * @throws IOException if an IO error occurs - */ - public void streamClosed(boolean inStream) throws IOException { - - } - - public void noBodyHeader(){ - mSendBodyHeader = false; - } -} diff --git a/obex/javax/obex/ServerRequestHandler.java b/obex/javax/obex/ServerRequestHandler.java deleted file mode 100644 index 09cbc2ca489f..000000000000 --- a/obex/javax/obex/ServerRequestHandler.java +++ /dev/null @@ -1,287 +0,0 @@ -/* - * Copyright (c) 2008-2009, Motorola, Inc. - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * - Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * - Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * - Neither the name of the Motorola, Inc. nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -package javax.obex; - -/** - * The ServerRequestHandler class defines an event listener that - * will respond to OBEX requests made to the server. - *

- * The onConnect(), onSetPath(), - * onDelete(), onGet(), and onPut() - * methods may return any response code defined in the - * ResponseCodes class except for OBEX_HTTP_CONTINUE. - * If OBEX_HTTP_CONTINUE or a value not defined in the - * ResponseCodes class is returned, the server implementation will - * send an OBEX_HTTP_INTERNAL_ERROR response to the client. - *

- * Connection ID and Target Headers - *

- * According to the IrOBEX specification, a packet may not contain a Connection - * ID and Target header. Since the Connection ID header is managed by the - * implementation, it will not send a Connection ID header, if a Connection ID - * was specified, in a packet that has a Target header. In other words, if an - * application adds a Target header to a HeaderSet object used in - * an OBEX operation and a Connection ID was specified, no Connection ID will be - * sent in the packet containing the Target header. - *

- * CREATE-EMPTY Requests - *

- * A CREATE-EMPTY request allows clients to create empty objects on the server. - * When a CREATE-EMPTY request is received, the onPut() method will - * be called by the implementation. To differentiate between a normal PUT - * request and a CREATE-EMPTY request, an application must open the - * InputStream from the Operation object passed to the - * onPut() method. For a PUT request, the application will be able - * to read Body data from this InputStream. For a CREATE-EMPTY - * request, there will be no Body data to read. Therefore, a call to - * InputStream.read() will return -1. - * @hide - */ -public class ServerRequestHandler { - - private long mConnectionId; - - /** - * Creates a ServerRequestHandler. - */ - protected ServerRequestHandler() { - /* - * A connection ID of -1 implies there is no conenction ID - */ - mConnectionId = -1; - } - - /** - * Sets the connection ID header to include in the reply packets. - * @param connectionId the connection ID to use; -1 if no connection ID - * should be sent - * @throws IllegalArgumentException if id is not in the range - * -1 to 232-1 - */ - public void setConnectionId(final long connectionId) { - if ((connectionId < -1) || (connectionId > 0xFFFFFFFFL)) { - throw new IllegalArgumentException("Illegal Connection ID"); - } - mConnectionId = connectionId; - } - - /** - * Retrieves the connection ID that is being used in the present connection. - * This method will return -1 if no connection ID is being used. - * @return the connection id being used or -1 if no connection ID is being - * used - */ - public long getConnectionId() { - return mConnectionId; - } - - /** - * Called when a CONNECT request is received. - *

- * If this method is not implemented by the class that extends this class, - * onConnect() will always return an OBEX_HTTP_OK - * response code. - *

- * The headers received in the request can be retrieved from the - * request argument. The headers that should be sent in the - * reply must be specified in the reply argument. - * @param request contains the headers sent by the client; - * request will never be null - * @param reply the headers that should be sent in the reply; - * reply will never be null - * @return a response code defined in ResponseCodes that will - * be returned to the client; if an invalid response code is - * provided, the OBEX_HTTP_INTERNAL_ERROR response code - * will be used - */ - public int onConnect(HeaderSet request, HeaderSet reply) { - return ResponseCodes.OBEX_HTTP_OK; - } - - /** - * Called when a DISCONNECT request is received. - *

- * The headers received in the request can be retrieved from the - * request argument. The headers that should be sent in the - * reply must be specified in the reply argument. - * @param request contains the headers sent by the client; - * request will never be null - * @param reply the headers that should be sent in the reply; - * reply will never be null - */ - public void onDisconnect(HeaderSet request, HeaderSet reply) { - } - - /** - * Called when a SETPATH request is received. - *

- * If this method is not implemented by the class that extends this class, - * onSetPath() will always return an - * OBEX_HTTP_NOT_IMPLEMENTED response code. - *

- * The headers received in the request can be retrieved from the - * request argument. The headers that should be sent in the - * reply must be specified in the reply argument. - * @param request contains the headers sent by the client; - * request will never be null - * @param reply the headers that should be sent in the reply; - * reply will never be null - * @param backup true if the client requests that the server - * back up one directory before changing to the path described by - * name; false to apply the request to the - * present path - * @param create true if the path should be created if it does - * not already exist; false if the path should not be - * created if it does not exist and an error code should be returned - * @return a response code defined in ResponseCodes that will - * be returned to the client; if an invalid response code is - * provided, the OBEX_HTTP_INTERNAL_ERROR response code - * will be used - */ - public int onSetPath(HeaderSet request, HeaderSet reply, boolean backup, boolean create) { - - return ResponseCodes.OBEX_HTTP_NOT_IMPLEMENTED; - } - - /** - * Called when a DELETE request is received. - *

- * If this method is not implemented by the class that extends this class, - * onDelete() will always return an - * OBEX_HTTP_NOT_IMPLEMENTED response code. - *

- * The headers received in the request can be retrieved from the - * request argument. The headers that should be sent in the - * reply must be specified in the reply argument. - * @param request contains the headers sent by the client; - * request will never be null - * @param reply the headers that should be sent in the reply; - * reply will never be null - * @return a response code defined in ResponseCodes that will - * be returned to the client; if an invalid response code is - * provided, the OBEX_HTTP_INTERNAL_ERROR response code - * will be used - */ - public int onDelete(HeaderSet request, HeaderSet reply) { - return ResponseCodes.OBEX_HTTP_NOT_IMPLEMENTED; - } - - /** - * Called when a ABORT request is received. - */ - public int onAbort(HeaderSet request, HeaderSet reply) { - return ResponseCodes.OBEX_HTTP_NOT_IMPLEMENTED; - } - - /** - * Called when a PUT request is received. - *

- * If this method is not implemented by the class that extends this class, - * onPut() will always return an - * OBEX_HTTP_NOT_IMPLEMENTED response code. - *

- * If an ABORT request is received during the processing of a PUT request, - * op will be closed by the implementation. - * @param operation contains the headers sent by the client and allows new - * headers to be sent in the reply; op will never be - * null - * @return a response code defined in ResponseCodes that will - * be returned to the client; if an invalid response code is - * provided, the OBEX_HTTP_INTERNAL_ERROR response code - * will be used - */ - public int onPut(Operation operation) { - return ResponseCodes.OBEX_HTTP_NOT_IMPLEMENTED; - } - - /** - * Called when a GET request is received. - *

- * If this method is not implemented by the class that extends this class, - * onGet() will always return an - * OBEX_HTTP_NOT_IMPLEMENTED response code. - *

- * If an ABORT request is received during the processing of a GET request, - * op will be closed by the implementation. - * @param operation contains the headers sent by the client and allows new - * headers to be sent in the reply; op will never be - * null - * @return a response code defined in ResponseCodes that will - * be returned to the client; if an invalid response code is - * provided, the OBEX_HTTP_INTERNAL_ERROR response code - * will be used - */ - public int onGet(Operation operation) { - return ResponseCodes.OBEX_HTTP_NOT_IMPLEMENTED; - } - - /** - * Called when this object attempts to authenticate a client and the - * authentication request fails because the response digest in the - * authentication response header was wrong. - *

- * If this method is not implemented by the class that extends this class, - * this method will do nothing. - * @param userName the user name returned in the authentication response; - * null if no user name was provided in the response - */ - public void onAuthenticationFailure(byte[] userName) { - } - - /** - * Called by ServerSession to update the status of current transaction - *

- * If this method is not implemented by the class that extends this class, - * this method will do nothing. - */ - public void updateStatus(String message) { - } - - /** - * Called when session is closed. - *

- * If this method is not implemented by the class that extends this class, - * this method will do nothing. - */ - public void onClose() { - } - - /** - * Override to add Single Response Mode support - e.g. if the supplied - * transport is l2cap. - * @return True if SRM is supported, else False - */ - public boolean isSrmSupported() { - return false; - } -} diff --git a/obex/javax/obex/ServerSession.java b/obex/javax/obex/ServerSession.java deleted file mode 100644 index dbfeefdfb037..000000000000 --- a/obex/javax/obex/ServerSession.java +++ /dev/null @@ -1,742 +0,0 @@ -/* - * Copyright (C) 2015 The Android Open Source Project - * Copyright (c) 2015 Samsung LSI - * Copyright (c) 2008-2009, Motorola, Inc. - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * - Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * - Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * - Neither the name of the Motorola, Inc. nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -package javax.obex; - -import android.util.Log; - -import java.io.InputStream; -import java.io.IOException; -import java.io.OutputStream; - -/** - * This class in an implementation of the OBEX ServerSession. - * @hide - */ -public final class ServerSession extends ObexSession implements Runnable { - - private static final String TAG = "Obex ServerSession"; - private static final boolean V = ObexHelper.VDBG; - - private ObexTransport mTransport; - - private InputStream mInput; - - private OutputStream mOutput; - - private ServerRequestHandler mListener; - - private Thread mProcessThread; - - private int mMaxPacketLength; - - private boolean mClosed; - - /** - * Creates new ServerSession. - * @param trans the connection to the client - * @param handler the event listener that will process requests - * @param auth the authenticator to use with this connection - * @throws IOException if an error occurred while opening the input and - * output streams - */ - public ServerSession(ObexTransport trans, ServerRequestHandler handler, Authenticator auth) - throws IOException { - mAuthenticator = auth; - mTransport = trans; - mInput = mTransport.openInputStream(); - mOutput = mTransport.openOutputStream(); - mListener = handler; - mMaxPacketLength = 256; - - mClosed = false; - mProcessThread = new Thread(this); - mProcessThread.start(); - } - - /** - * Processes requests made to the server and forwards them to the - * appropriate event listener. - */ - public void run() { - try { - - boolean done = false; - while (!done && !mClosed) { - if(V) Log.v(TAG, "Waiting for incoming request..."); - int requestType = mInput.read(); - if(V) Log.v(TAG, "Read request: " + requestType); - switch (requestType) { - case ObexHelper.OBEX_OPCODE_CONNECT: - handleConnectRequest(); - break; - - case ObexHelper.OBEX_OPCODE_DISCONNECT: - handleDisconnectRequest(); - break; - - case ObexHelper.OBEX_OPCODE_GET: - case ObexHelper.OBEX_OPCODE_GET_FINAL: - handleGetRequest(requestType); - break; - - case ObexHelper.OBEX_OPCODE_PUT: - case ObexHelper.OBEX_OPCODE_PUT_FINAL: - handlePutRequest(requestType); - break; - - case ObexHelper.OBEX_OPCODE_SETPATH: - handleSetPathRequest(); - break; - case ObexHelper.OBEX_OPCODE_ABORT: - handleAbortRequest(); - break; - - case -1: - done = true; - break; - - default: - - /* - * Received a request type that is not recognized so I am - * just going to read the packet and send a not implemented - * to the client - */ - int length = mInput.read(); - length = (length << 8) + mInput.read(); - for (int i = 3; i < length; i++) { - mInput.read(); - } - sendResponse(ResponseCodes.OBEX_HTTP_NOT_IMPLEMENTED, null); - } - } - - } catch (NullPointerException e) { - Log.d(TAG, "Exception occured - ignoring", e); - } catch (Exception e) { - Log.d(TAG, "Exception occured - ignoring", e); - } - close(); - } - - /** - * Handles a ABORT request from a client. This method will read the rest of - * the request from the client. Assuming the request is valid, it will - * create a HeaderSet object to pass to the - * ServerRequestHandler object. After the handler processes the - * request, this method will create a reply message to send to the server. - * - * @throws IOException if an error occurred at the transport layer - */ - private void handleAbortRequest() throws IOException { - int code = ResponseCodes.OBEX_HTTP_OK; - HeaderSet request = new HeaderSet(); - HeaderSet reply = new HeaderSet(); - - int length = mInput.read(); - length = (length << 8) + mInput.read(); - if (length > ObexHelper.getMaxRxPacketSize(mTransport)) { - code = ResponseCodes.OBEX_HTTP_REQ_TOO_LARGE; - } else { - for (int i = 3; i < length; i++) { - mInput.read(); - } - code = mListener.onAbort(request, reply); - Log.v(TAG, "onAbort request handler return value- " + code); - code = validateResponseCode(code); - } - sendResponse(code, null); - } - - /** - * Handles a PUT request from a client. This method will provide a - * ServerOperation object to the request handler. The - * ServerOperation object will handle the rest of the request. - * It will also send replies and receive requests until the final reply - * should be sent. When the final reply should be sent, this method will get - * the response code to use and send the reply. The - * ServerOperation object will always reply with a - * OBEX_HTTP_CONTINUE reply. It will only reply if further information is - * needed. - * @param type the type of request received; either 0x02 or 0x82 - * @throws IOException if an error occurred at the transport layer - */ - private void handlePutRequest(int type) throws IOException { - ServerOperation op = new ServerOperation(this, mInput, type, mMaxPacketLength, mListener); - try { - int response = -1; - - if ((op.finalBitSet) && !op.isValidBody()) { - response = validateResponseCode(mListener - .onDelete(op.requestHeader, op.replyHeader)); - } else { - response = validateResponseCode(mListener.onPut(op)); - } - if (response != ResponseCodes.OBEX_HTTP_OK && !op.isAborted) { - op.sendReply(response); - } else if (!op.isAborted) { - // wait for the final bit - while (!op.finalBitSet) { - op.sendReply(ResponseCodes.OBEX_HTTP_CONTINUE); - } - op.sendReply(response); - } - } catch (Exception e) { - /*To fix bugs in aborted cases, - *(client abort file transfer prior to the last packet which has the end of body header, - *internal error should not be sent because server has already replied with - *OK response in "sendReply") - */ - if(V) Log.d(TAG,"Exception occured - sending OBEX_HTTP_INTERNAL_ERROR reply",e); - if (!op.isAborted) { - sendResponse(ResponseCodes.OBEX_HTTP_INTERNAL_ERROR, null); - } - } - } - - /** - * Handles a GET request from a client. This method will provide a - * ServerOperation object to the request handler. The - * ServerOperation object will handle the rest of the request. - * It will also send replies and receive requests until the final reply - * should be sent. When the final reply should be sent, this method will get - * the response code to use and send the reply. The - * ServerOperation object will always reply with a - * OBEX_HTTP_CONTINUE reply. It will only reply if further information is - * needed. - * @param type the type of request received; either 0x03 or 0x83 - * @throws IOException if an error occurred at the transport layer - */ - private void handleGetRequest(int type) throws IOException { - ServerOperation op = new ServerOperation(this, mInput, type, mMaxPacketLength, mListener); - try { - int response = validateResponseCode(mListener.onGet(op)); - - if (!op.isAborted) { - op.sendReply(response); - } - } catch (Exception e) { - if(V) Log.d(TAG,"Exception occured - sending OBEX_HTTP_INTERNAL_ERROR reply",e); - sendResponse(ResponseCodes.OBEX_HTTP_INTERNAL_ERROR, null); - } - } - - /** - * Send standard response. - * @param code the response code to send - * @param header the headers to include in the response - * @throws IOException if an IO error occurs - */ - public void sendResponse(int code, byte[] header) throws IOException { - int totalLength = 3; - byte[] data = null; - OutputStream op = mOutput; - if (op == null) { - return; - } - - if (header != null) { - totalLength += header.length; - data = new byte[totalLength]; - data[0] = (byte)code; - data[1] = (byte)(totalLength >> 8); - data[2] = (byte)totalLength; - System.arraycopy(header, 0, data, 3, header.length); - } else { - data = new byte[totalLength]; - data[0] = (byte)code; - data[1] = (byte)0x00; - data[2] = (byte)totalLength; - } - op.write(data); - op.flush(); // TODO: Do we need to flush? - } - - /** - * Handles a SETPATH request from a client. This method will read the rest - * of the request from the client. Assuming the request is valid, it will - * create a HeaderSet object to pass to the - * ServerRequestHandler object. After the handler processes the - * request, this method will create a reply message to send to the server - * with the response code provided. - * @throws IOException if an error occurred at the transport layer - */ - private void handleSetPathRequest() throws IOException { - int length; - int flags; - @SuppressWarnings("unused") - int constants; - int totalLength = 3; - byte[] head = null; - int code = -1; - int bytesReceived; - HeaderSet request = new HeaderSet(); - HeaderSet reply = new HeaderSet(); - - length = mInput.read(); - length = (length << 8) + mInput.read(); - flags = mInput.read(); - constants = mInput.read(); - - if (length > ObexHelper.getMaxRxPacketSize(mTransport)) { - code = ResponseCodes.OBEX_HTTP_REQ_TOO_LARGE; - totalLength = 3; - } else { - if (length > 5) { - byte[] headers = new byte[length - 5]; - bytesReceived = mInput.read(headers); - - while (bytesReceived != headers.length) { - bytesReceived += mInput.read(headers, bytesReceived, headers.length - - bytesReceived); - } - - ObexHelper.updateHeaderSet(request, headers); - - if (mListener.getConnectionId() != -1 && request.mConnectionID != null) { - mListener.setConnectionId(ObexHelper.convertToLong(request.mConnectionID)); - } else { - mListener.setConnectionId(1); - } - // the Auth chan is initiated by the server, client sent back the authResp . - if (request.mAuthResp != null) { - if (!handleAuthResp(request.mAuthResp)) { - code = ResponseCodes.OBEX_HTTP_UNAUTHORIZED; - mListener.onAuthenticationFailure(ObexHelper.getTagValue((byte)0x01, - request.mAuthResp)); - } - request.mAuthResp = null; - } - } - - if (code != ResponseCodes.OBEX_HTTP_UNAUTHORIZED) { - // the Auth challenge is initiated by the client - // the server will send back the authResp to the client - if (request.mAuthChall != null) { - handleAuthChall(request); - reply.mAuthResp = new byte[request.mAuthResp.length]; - System.arraycopy(request.mAuthResp, 0, reply.mAuthResp, 0, - reply.mAuthResp.length); - request.mAuthChall = null; - request.mAuthResp = null; - } - boolean backup = false; - boolean create = true; - if (!((flags & 1) == 0)) { - backup = true; - } - if (!((flags & 2) == 0)) { - create = false; - } - - try { - code = mListener.onSetPath(request, reply, backup, create); - } catch (Exception e) { - if(V) Log.d(TAG,"Exception occured - sending OBEX_HTTP_INTERNAL_ERROR reply",e); - sendResponse(ResponseCodes.OBEX_HTTP_INTERNAL_ERROR, null); - return; - } - - code = validateResponseCode(code); - - if (reply.nonce != null) { - mChallengeDigest = new byte[16]; - System.arraycopy(reply.nonce, 0, mChallengeDigest, 0, 16); - } else { - mChallengeDigest = null; - } - - long id = mListener.getConnectionId(); - if (id == -1) { - reply.mConnectionID = null; - } else { - reply.mConnectionID = ObexHelper.convertToByteArray(id); - } - - head = ObexHelper.createHeader(reply, false); - totalLength += head.length; - - if (totalLength > mMaxPacketLength) { - totalLength = 3; - head = null; - code = ResponseCodes.OBEX_HTTP_INTERNAL_ERROR; - } - } - } - - // Compute Length of OBEX SETPATH packet - byte[] replyData = new byte[totalLength]; - replyData[0] = (byte)code; - replyData[1] = (byte)(totalLength >> 8); - replyData[2] = (byte)totalLength; - if (head != null) { - System.arraycopy(head, 0, replyData, 3, head.length); - } - /* - * Write the OBEX SETPATH packet to the server. Byte 0: response code - * Byte 1&2: Connect Packet Length Byte 3 to n: headers - */ - mOutput.write(replyData); - mOutput.flush(); - } - - /** - * Handles a disconnect request from a client. This method will read the - * rest of the request from the client. Assuming the request is valid, it - * will create a HeaderSet object to pass to the - * ServerRequestHandler object. After the handler processes the - * request, this method will create a reply message to send to the server. - * @throws IOException if an error occurred at the transport layer - */ - private void handleDisconnectRequest() throws IOException { - int length; - int code = ResponseCodes.OBEX_HTTP_OK; - int totalLength = 3; - byte[] head = null; - int bytesReceived; - HeaderSet request = new HeaderSet(); - HeaderSet reply = new HeaderSet(); - - length = mInput.read(); - length = (length << 8) + mInput.read(); - - if (length > ObexHelper.getMaxRxPacketSize(mTransport)) { - code = ResponseCodes.OBEX_HTTP_REQ_TOO_LARGE; - totalLength = 3; - } else { - if (length > 3) { - byte[] headers = new byte[length - 3]; - bytesReceived = mInput.read(headers); - - while (bytesReceived != headers.length) { - bytesReceived += mInput.read(headers, bytesReceived, headers.length - - bytesReceived); - } - - ObexHelper.updateHeaderSet(request, headers); - } - - if (mListener.getConnectionId() != -1 && request.mConnectionID != null) { - mListener.setConnectionId(ObexHelper.convertToLong(request.mConnectionID)); - } else { - mListener.setConnectionId(1); - } - - if (request.mAuthResp != null) { - if (!handleAuthResp(request.mAuthResp)) { - code = ResponseCodes.OBEX_HTTP_UNAUTHORIZED; - mListener.onAuthenticationFailure(ObexHelper.getTagValue((byte)0x01, - request.mAuthResp)); - } - request.mAuthResp = null; - } - - if (code != ResponseCodes.OBEX_HTTP_UNAUTHORIZED) { - - if (request.mAuthChall != null) { - handleAuthChall(request); - request.mAuthChall = null; - } - - try { - mListener.onDisconnect(request, reply); - } catch (Exception e) { - if(V) Log.d(TAG,"Exception occured - sending OBEX_HTTP_INTERNAL_ERROR reply",e); - sendResponse(ResponseCodes.OBEX_HTTP_INTERNAL_ERROR, null); - return; - } - - long id = mListener.getConnectionId(); - if (id == -1) { - reply.mConnectionID = null; - } else { - reply.mConnectionID = ObexHelper.convertToByteArray(id); - } - - head = ObexHelper.createHeader(reply, false); - totalLength += head.length; - - if (totalLength > mMaxPacketLength) { - totalLength = 3; - head = null; - code = ResponseCodes.OBEX_HTTP_INTERNAL_ERROR; - } - } - } - - // Compute Length of OBEX CONNECT packet - byte[] replyData; - if (head != null) { - replyData = new byte[3 + head.length]; - } else { - replyData = new byte[3]; - } - replyData[0] = (byte)code; - replyData[1] = (byte)(totalLength >> 8); - replyData[2] = (byte)totalLength; - if (head != null) { - System.arraycopy(head, 0, replyData, 3, head.length); - } - /* - * Write the OBEX DISCONNECT packet to the server. Byte 0: response code - * Byte 1&2: Connect Packet Length Byte 3 to n: headers - */ - mOutput.write(replyData); - mOutput.flush(); - } - - /** - * Handles a connect request from a client. This method will read the rest - * of the request from the client. Assuming the request is valid, it will - * create a HeaderSet object to pass to the - * ServerRequestHandler object. After the handler processes the - * request, this method will create a reply message to send to the server - * with the response code provided. - * @throws IOException if an error occurred at the transport layer - */ - private void handleConnectRequest() throws IOException { - int packetLength; - @SuppressWarnings("unused") - int version; - @SuppressWarnings("unused") - int flags; - int totalLength = 7; - byte[] head = null; - int code = -1; - HeaderSet request = new HeaderSet(); - HeaderSet reply = new HeaderSet(); - int bytesReceived; - - if(V) Log.v(TAG,"handleConnectRequest()"); - - /* - * Read in the length of the OBEX packet, OBEX version, flags, and max - * packet length - */ - packetLength = mInput.read(); - packetLength = (packetLength << 8) + mInput.read(); - if(V) Log.v(TAG,"handleConnectRequest() - packetLength: " + packetLength); - - version = mInput.read(); - flags = mInput.read(); - mMaxPacketLength = mInput.read(); - mMaxPacketLength = (mMaxPacketLength << 8) + mInput.read(); - - if(V) Log.v(TAG,"handleConnectRequest() - version: " + version - + " MaxLength: " + mMaxPacketLength + " flags: " + flags); - - // should we check it? - if (mMaxPacketLength > ObexHelper.MAX_PACKET_SIZE_INT) { - mMaxPacketLength = ObexHelper.MAX_PACKET_SIZE_INT; - } - - if(mMaxPacketLength > ObexHelper.getMaxTxPacketSize(mTransport)) { - Log.w(TAG, "Requested MaxObexPacketSize " + mMaxPacketLength - + " is larger than the max size supported by the transport: " - + ObexHelper.getMaxTxPacketSize(mTransport) - + " Reducing to this size."); - mMaxPacketLength = ObexHelper.getMaxTxPacketSize(mTransport); - } - - if (packetLength > ObexHelper.getMaxRxPacketSize(mTransport)) { - code = ResponseCodes.OBEX_HTTP_REQ_TOO_LARGE; - totalLength = 7; - } else { - if (packetLength > 7) { - byte[] headers = new byte[packetLength - 7]; - bytesReceived = mInput.read(headers); - - while (bytesReceived != headers.length) { - bytesReceived += mInput.read(headers, bytesReceived, headers.length - - bytesReceived); - } - - ObexHelper.updateHeaderSet(request, headers); - } - - if (mListener.getConnectionId() != -1 && request.mConnectionID != null) { - mListener.setConnectionId(ObexHelper.convertToLong(request.mConnectionID)); - } else { - mListener.setConnectionId(1); - } - - if (request.mAuthResp != null) { - if (!handleAuthResp(request.mAuthResp)) { - code = ResponseCodes.OBEX_HTTP_UNAUTHORIZED; - mListener.onAuthenticationFailure(ObexHelper.getTagValue((byte)0x01, - request.mAuthResp)); - } - request.mAuthResp = null; - } - - if (code != ResponseCodes.OBEX_HTTP_UNAUTHORIZED) { - if (request.mAuthChall != null) { - handleAuthChall(request); - reply.mAuthResp = new byte[request.mAuthResp.length]; - System.arraycopy(request.mAuthResp, 0, reply.mAuthResp, 0, - reply.mAuthResp.length); - request.mAuthChall = null; - request.mAuthResp = null; - } - - try { - code = mListener.onConnect(request, reply); - code = validateResponseCode(code); - - if (reply.nonce != null) { - mChallengeDigest = new byte[16]; - System.arraycopy(reply.nonce, 0, mChallengeDigest, 0, 16); - } else { - mChallengeDigest = null; - } - long id = mListener.getConnectionId(); - if (id == -1) { - reply.mConnectionID = null; - } else { - reply.mConnectionID = ObexHelper.convertToByteArray(id); - } - - head = ObexHelper.createHeader(reply, false); - totalLength += head.length; - - if (totalLength > mMaxPacketLength) { - totalLength = 7; - head = null; - code = ResponseCodes.OBEX_HTTP_INTERNAL_ERROR; - } - } catch (Exception e) { - if(V) Log.d(TAG,"Exception occured - sending OBEX_HTTP_INTERNAL_ERROR reply",e); - totalLength = 7; - head = null; - code = ResponseCodes.OBEX_HTTP_INTERNAL_ERROR; - } - - } - } - - // Compute Length of OBEX CONNECT packet - byte[] length = ObexHelper.convertToByteArray(totalLength); - - /* - * Write the OBEX CONNECT packet to the server. Byte 0: response code - * Byte 1&2: Connect Packet Length Byte 3: OBEX Version Number - * (Presently, 0x10) Byte 4: Flags (For TCP 0x00) Byte 5&6: Max OBEX - * Packet Length (Defined in MAX_PACKET_SIZE) Byte 7 to n: headers - */ - byte[] sendData = new byte[totalLength]; - int maxRxLength = ObexHelper.getMaxRxPacketSize(mTransport); - if (maxRxLength > mMaxPacketLength) { - if(V) Log.v(TAG,"Set maxRxLength to min of maxRxServrLen:" + maxRxLength + - " and MaxNegotiated from Client: " + mMaxPacketLength); - maxRxLength = mMaxPacketLength; - } - sendData[0] = (byte)code; - sendData[1] = length[2]; - sendData[2] = length[3]; - sendData[3] = (byte)0x10; - sendData[4] = (byte)0x00; - sendData[5] = (byte)(maxRxLength >> 8); - sendData[6] = (byte)(maxRxLength & 0xFF); - - if (head != null) { - System.arraycopy(head, 0, sendData, 7, head.length); - } - - mOutput.write(sendData); - mOutput.flush(); - } - - /** - * Closes the server session - in detail close I/O streams and the - * underlying transport layer. Internal flag is also set so that later - * attempt to read/write will throw an exception. - */ - public synchronized void close() { - if (mListener != null) { - mListener.onClose(); - } - try { - /* Set state to closed before interrupting the thread by closing the streams */ - mClosed = true; - if(mInput != null) - mInput.close(); - if(mOutput != null) - mOutput.close(); - if(mTransport != null) - mTransport.close(); - } catch (Exception e) { - if(V) Log.d(TAG,"Exception occured during close() - ignore",e); - } - mTransport = null; - mInput = null; - mOutput = null; - mListener = null; - } - - /** - * Verifies that the response code is valid. If it is not valid, it will - * return the OBEX_HTTP_INTERNAL_ERROR response code. - * @param code the response code to check - * @return the valid response code or OBEX_HTTP_INTERNAL_ERROR - * if code is not valid - */ - private int validateResponseCode(int code) { - - if ((code >= ResponseCodes.OBEX_HTTP_OK) && (code <= ResponseCodes.OBEX_HTTP_PARTIAL)) { - return code; - } - if ((code >= ResponseCodes.OBEX_HTTP_MULT_CHOICE) - && (code <= ResponseCodes.OBEX_HTTP_USE_PROXY)) { - return code; - } - if ((code >= ResponseCodes.OBEX_HTTP_BAD_REQUEST) - && (code <= ResponseCodes.OBEX_HTTP_UNSUPPORTED_TYPE)) { - return code; - } - if ((code >= ResponseCodes.OBEX_HTTP_INTERNAL_ERROR) - && (code <= ResponseCodes.OBEX_HTTP_VERSION)) { - return code; - } - if ((code >= ResponseCodes.OBEX_DATABASE_FULL) - && (code <= ResponseCodes.OBEX_DATABASE_LOCKED)) { - return code; - } - return ResponseCodes.OBEX_HTTP_INTERNAL_ERROR; - } - - public ObexTransport getTransport() { - return mTransport; - } -} diff --git a/obex/javax/obex/SessionNotifier.java b/obex/javax/obex/SessionNotifier.java deleted file mode 100644 index 9836dd60f2c6..000000000000 --- a/obex/javax/obex/SessionNotifier.java +++ /dev/null @@ -1,128 +0,0 @@ -/* - * Copyright (c) 2008-2009, Motorola, Inc. - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * - Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * - Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * - Neither the name of the Motorola, Inc. nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -package javax.obex; - -import java.io.IOException; - -/** - * The SessionNotifier interface defines a connection notifier for - * server-side OBEX connections. When a SessionNotifier is created - * and calls acceptAndOpen(), it will begin listening for clients - * to create a connection at the transport layer. When the transport layer - * connection is received, the acceptAndOpen() method will return a - * javax.microedition.io.Connection that is the connection to the - * client. The acceptAndOpen() method also takes a - * ServerRequestHandler argument that will process the requests - * from the client that connects to the server. - * @hide - */ -public interface SessionNotifier { - - /** - * Waits for a transport layer connection to be established and specifies - * the handler to handle the requests from the client. No authenticator is - * associated with this connection, therefore, it is implementation - * dependent as to how an authentication challenge and authentication - * response header will be received and processed. - *

- *

Additional Note for OBEX over Bluetooth

If this method is called - * on a SessionNotifier object that does not have a - * ServiceRecord in the SDDB, the ServiceRecord - * for this object will be added to the SDDB. This method requests the BCC - * to put the local device in connectable mode so that it will respond to - * connection attempts by clients. - *

- * The following checks are done to verify that the service record provided - * is valid. If any of these checks fail, then a - * ServiceRegistrationException is thrown. - *

- *

- * This method will not ensure that ServiceRecord associated - * with this notifier is a completely valid service record. It is the - * responsibility of the application to ensure that the service record - * follows all of the applicable syntactic and semantic rules for service - * record correctness. - * @param handler the request handler that will respond to OBEX requests - * @return the connection to the client - * @throws IOException if an error occurs in the transport layer - * @throws NullPointerException if handler is null - */ - ObexSession acceptAndOpen(ServerRequestHandler handler) throws IOException; - - /** - * Waits for a transport layer connection to be established and specifies - * the handler to handle the requests from the client and the - * Authenticator to use to respond to authentication challenge - * and authentication response headers. - *

- *

Additional Note for OBEX over Bluetooth

If this method is called - * on a SessionNotifier object that does not have a - * ServiceRecord in the SDDB, the ServiceRecord - * for this object will be added to the SDDB. This method requests the BCC - * to put the local device in connectable mode so that it will respond to - * connection attempts by clients. - *

- * The following checks are done to verify that the service record provided - * is valid. If any of these checks fail, then a - * ServiceRegistrationException is thrown. - *

- *

- * This method will not ensure that ServiceRecord associated - * with this notifier is a completely valid service record. It is the - * responsibility of the application to ensure that the service record - * follows all of the applicable syntactic and semantic rules for service - * record correctness. - * @param handler the request handler that will respond to OBEX requests - * @param auth the Authenticator to use with this connection; - * if null then no Authenticator will be - * used - * @return the connection to the client - * @throws IOException if an error occurs in the transport layer - * @throws NullPointerException if handler is null - */ - ObexSession acceptAndOpen(ServerRequestHandler handler, Authenticator auth) throws IOException; -}