19439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly/*
29439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * Copyright (c) 2008-2009, Motorola, Inc.
39439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly *
49439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * All rights reserved.
59439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly *
69439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * Redistribution and use in source and binary forms, with or without
79439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * modification, are permitted provided that the following conditions are met:
89439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly *
99439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * - Redistributions of source code must retain the above copyright notice,
109439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * this list of conditions and the following disclaimer.
119439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly *
129439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * - Redistributions in binary form must reproduce the above copyright notice,
139439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * this list of conditions and the following disclaimer in the documentation
149439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * and/or other materials provided with the distribution.
159439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly *
169439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * - Neither the name of the Motorola, Inc. nor the names of its contributors
179439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * may be used to endorse or promote products derived from this software
189439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * without specific prior written permission.
199439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly *
209439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
219439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
229439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
239439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
249439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
259439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
269439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
279439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
289439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
299439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
309439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * POSSIBILITY OF SUCH DAMAGE.
319439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly */
329439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
339439a7fe517b858bc5e5c654b459315e4722feb2Nick Pellypackage javax.obex;
349439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
359439a7fe517b858bc5e5c654b459315e4722feb2Nick Pellyimport java.io.ByteArrayOutputStream;
369439a7fe517b858bc5e5c654b459315e4722feb2Nick Pellyimport java.io.IOException;
379439a7fe517b858bc5e5c654b459315e4722feb2Nick Pellyimport java.io.InputStream;
389439a7fe517b858bc5e5c654b459315e4722feb2Nick Pellyimport java.io.OutputStream;
399439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
409439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly/**
413998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun * This class in an implementation of the OBEX ClientSession.
422e0da96e757a977154063f980d3f4e1abd41cf09Nick Pelly * @hide
439439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly */
443998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejunpublic final class ClientSession extends ObexSession {
459439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
4641557e18fa3fc5791a5a1c7f0051ae3385608bc4Nick Pelly    private boolean mOpen;
479439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
482e0da96e757a977154063f980d3f4e1abd41cf09Nick Pelly    // Determines if an OBEX layer connection has been established
4941557e18fa3fc5791a5a1c7f0051ae3385608bc4Nick Pelly    private boolean mObexConnected;
509439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
5141557e18fa3fc5791a5a1c7f0051ae3385608bc4Nick Pelly    private byte[] mConnectionId = null;
529439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
539439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    /*
5441557e18fa3fc5791a5a1c7f0051ae3385608bc4Nick Pelly     * The max Packet size must be at least 256 according to the OBEX
5541557e18fa3fc5791a5a1c7f0051ae3385608bc4Nick Pelly     * specification.
5641557e18fa3fc5791a5a1c7f0051ae3385608bc4Nick Pelly     */
579439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    private int maxPacketSize = 256;
589439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
5941557e18fa3fc5791a5a1c7f0051ae3385608bc4Nick Pelly    private boolean mRequestActive;
609439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
6141557e18fa3fc5791a5a1c7f0051ae3385608bc4Nick Pelly    private final InputStream mInput;
629439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
6341557e18fa3fc5791a5a1c7f0051ae3385608bc4Nick Pelly    private final OutputStream mOutput;
649439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
653998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun    public ClientSession(final ObexTransport trans) throws IOException {
6641557e18fa3fc5791a5a1c7f0051ae3385608bc4Nick Pelly        mInput = trans.openInputStream();
6741557e18fa3fc5791a5a1c7f0051ae3385608bc4Nick Pelly        mOutput = trans.openOutputStream();
6841557e18fa3fc5791a5a1c7f0051ae3385608bc4Nick Pelly        mOpen = true;
6941557e18fa3fc5791a5a1c7f0051ae3385608bc4Nick Pelly        mRequestActive = false;
709439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    }
719439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
723998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun    public HeaderSet connect(final HeaderSet header) throws IOException {
739439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        ensureOpen();
7441557e18fa3fc5791a5a1c7f0051ae3385608bc4Nick Pelly        if (mObexConnected) {
759439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            throw new IOException("Already connected to server");
769439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        }
7741557e18fa3fc5791a5a1c7f0051ae3385608bc4Nick Pelly        setRequestActive();
7841557e18fa3fc5791a5a1c7f0051ae3385608bc4Nick Pelly
799439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        int totalLength = 4;
809439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        byte[] head = null;
819439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
829439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        // Determine the header byte array
839439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        if (header != null) {
8441557e18fa3fc5791a5a1c7f0051ae3385608bc4Nick Pelly            if (header.nonce != null) {
8541557e18fa3fc5791a5a1c7f0051ae3385608bc4Nick Pelly                mChallengeDigest = new byte[16];
8641557e18fa3fc5791a5a1c7f0051ae3385608bc4Nick Pelly                System.arraycopy(header.nonce, 0, mChallengeDigest, 0, 16);
879439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            }
882e0da96e757a977154063f980d3f4e1abd41cf09Nick Pelly            head = ObexHelper.createHeader(header, false);
899439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            totalLength += head.length;
909439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        }
919439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        /*
929439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        * Write the OBEX CONNECT packet to the server.
939439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        * Byte 0: 0x80
949439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        * Byte 1&2: Connect Packet Length
959439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        * Byte 3: OBEX Version Number (Presently, 0x10)
969439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        * Byte 4: Flags (For TCP 0x00)
979439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        * Byte 5&6: Max OBEX Packet Length (Defined in MAX_PACKET_SIZE)
989439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        * Byte 7 to n: headers
999439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        */
1009439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        byte[] requestPacket = new byte[totalLength];
1019439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        // We just need to start at  byte 3 since the sendRequest() method will
1029439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        // handle the length and 0x80.
1039439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        requestPacket[0] = (byte)0x10;
1049439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        requestPacket[1] = (byte)0x00;
1052e0da96e757a977154063f980d3f4e1abd41cf09Nick Pelly        requestPacket[2] = (byte)(ObexHelper.MAX_PACKET_SIZE_INT >> 8);
1062e0da96e757a977154063f980d3f4e1abd41cf09Nick Pelly        requestPacket[3] = (byte)(ObexHelper.MAX_PACKET_SIZE_INT & 0xFF);
1079439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        if (head != null) {
1089439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            System.arraycopy(head, 0, requestPacket, 4, head.length);
1099439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        }
1109439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
1119439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        // check with local max packet size
1122e0da96e757a977154063f980d3f4e1abd41cf09Nick Pelly        if ((requestPacket.length + 3) > ObexHelper.MAX_PACKET_SIZE_INT) {
1139439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            throw new IOException("Packet size exceeds max packet size");
1149439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        }
1159439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
1169439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        HeaderSet returnHeaderSet = new HeaderSet();
1173998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun        sendRequest(ObexHelper.OBEX_OPCODE_CONNECT, requestPacket, returnHeaderSet, null);
1189439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
1199439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        /*
1209439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        * Read the response from the OBEX server.
1219439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        * Byte 0: Response Code (If successful then OBEX_HTTP_OK)
1229439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        * Byte 1&2: Packet Length
1239439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        * Byte 3: OBEX Version Number
1249439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        * Byte 4: Flags3
1259439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        * Byte 5&6: Max OBEX packet Length
1269439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        * Byte 7 to n: Optional HeaderSet
1279439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        */
1289439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        if (returnHeaderSet.responseCode == ResponseCodes.OBEX_HTTP_OK) {
12941557e18fa3fc5791a5a1c7f0051ae3385608bc4Nick Pelly            mObexConnected = true;
1309439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        }
13141557e18fa3fc5791a5a1c7f0051ae3385608bc4Nick Pelly        setRequestInactive();
1329439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
1339439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        return returnHeaderSet;
1349439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    }
1359439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
13641557e18fa3fc5791a5a1c7f0051ae3385608bc4Nick Pelly    public Operation get(HeaderSet header) throws IOException {
1379439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
13841557e18fa3fc5791a5a1c7f0051ae3385608bc4Nick Pelly        if (!mObexConnected) {
1399439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            throw new IOException("Not connected to the server");
1409439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        }
14141557e18fa3fc5791a5a1c7f0051ae3385608bc4Nick Pelly        setRequestActive();
14241557e18fa3fc5791a5a1c7f0051ae3385608bc4Nick Pelly
1439439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        ensureOpen();
1449439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
1453998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun        HeaderSet head;
1469439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        if (header == null) {
1473998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun            head = new HeaderSet();
1489439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        } else {
1493998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun            head = header;
1503998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun            if (head.nonce != null) {
15141557e18fa3fc5791a5a1c7f0051ae3385608bc4Nick Pelly                mChallengeDigest = new byte[16];
1523998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun                System.arraycopy(head.nonce, 0, mChallengeDigest, 0, 16);
1539439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            }
1549439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        }
1559439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        // Add the connection ID if one exists
15641557e18fa3fc5791a5a1c7f0051ae3385608bc4Nick Pelly        if (mConnectionId != null) {
1573998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun            head.mConnectionID = new byte[4];
1583998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun            System.arraycopy(mConnectionId, 0, head.mConnectionID, 0, 4);
1599439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        }
1609439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
1613998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun        return new ClientOperation(maxPacketSize, this, head, true);
1629439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    }
1639439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
1649439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    /**
16505ff98bbefda39b9ff26f8bca132cfd0248745c6Tao Liejun     * 0xCB Connection Id an identifier used for OBEX connection multiplexing
16641557e18fa3fc5791a5a1c7f0051ae3385608bc4Nick Pelly     */
1679439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    public void setConnectionID(long id) {
1689439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        if ((id < 0) || (id > 0xFFFFFFFFL)) {
1699439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            throw new IllegalArgumentException("Connection ID is not in a valid range");
1709439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        }
17141557e18fa3fc5791a5a1c7f0051ae3385608bc4Nick Pelly        mConnectionId = ObexHelper.convertToByteArray(id);
1729439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    }
1739439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
17441557e18fa3fc5791a5a1c7f0051ae3385608bc4Nick Pelly    public HeaderSet delete(HeaderSet header) throws IOException {
1759439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
17641557e18fa3fc5791a5a1c7f0051ae3385608bc4Nick Pelly        Operation op = put(header);
1779439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        op.getResponseCode();
1783998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun        HeaderSet returnValue = op.getReceivedHeader();
1799439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        op.close();
1809439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
1819439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        return returnValue;
1829439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    }
1839439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
18441557e18fa3fc5791a5a1c7f0051ae3385608bc4Nick Pelly    public HeaderSet disconnect(HeaderSet header) throws IOException {
18541557e18fa3fc5791a5a1c7f0051ae3385608bc4Nick Pelly        if (!mObexConnected) {
1869439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            throw new IOException("Not connected to the server");
1879439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        }
18841557e18fa3fc5791a5a1c7f0051ae3385608bc4Nick Pelly        setRequestActive();
18941557e18fa3fc5791a5a1c7f0051ae3385608bc4Nick Pelly
1909439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        ensureOpen();
1919439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        // Determine the header byte array
1929439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        byte[] head = null;
1939439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        if (header != null) {
19441557e18fa3fc5791a5a1c7f0051ae3385608bc4Nick Pelly            if (header.nonce != null) {
19541557e18fa3fc5791a5a1c7f0051ae3385608bc4Nick Pelly                mChallengeDigest = new byte[16];
19641557e18fa3fc5791a5a1c7f0051ae3385608bc4Nick Pelly                System.arraycopy(header.nonce, 0, mChallengeDigest, 0, 16);
1979439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            }
1989439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            // Add the connection ID if one exists
19941557e18fa3fc5791a5a1c7f0051ae3385608bc4Nick Pelly            if (mConnectionId != null) {
2003998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun                header.mConnectionID = new byte[4];
2013998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun                System.arraycopy(mConnectionId, 0, header.mConnectionID, 0, 4);
2029439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            }
2032e0da96e757a977154063f980d3f4e1abd41cf09Nick Pelly            head = ObexHelper.createHeader(header, false);
2049439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
2059439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            if ((head.length + 3) > maxPacketSize) {
2069439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                throw new IOException("Packet size exceeds max packet size");
2079439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            }
2089439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        } else {
2099439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            // Add the connection ID if one exists
21041557e18fa3fc5791a5a1c7f0051ae3385608bc4Nick Pelly            if (mConnectionId != null) {
2119439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                head = new byte[5];
2123998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun                head[0] = (byte)HeaderSet.CONNECTION_ID;
21341557e18fa3fc5791a5a1c7f0051ae3385608bc4Nick Pelly                System.arraycopy(mConnectionId, 0, head, 1, 4);
2149439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            }
2159439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        }
2169439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
2179439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        HeaderSet returnHeaderSet = new HeaderSet();
2183998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun        sendRequest(ObexHelper.OBEX_OPCODE_DISCONNECT, head, returnHeaderSet, null);
2199439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
2209439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        /*
22141557e18fa3fc5791a5a1c7f0051ae3385608bc4Nick Pelly         * An OBEX DISCONNECT reply from the server:
22241557e18fa3fc5791a5a1c7f0051ae3385608bc4Nick Pelly         * Byte 1: Response code
22341557e18fa3fc5791a5a1c7f0051ae3385608bc4Nick Pelly         * Bytes 2 & 3: packet size
22441557e18fa3fc5791a5a1c7f0051ae3385608bc4Nick Pelly         * Bytes 4 & up: headers
22541557e18fa3fc5791a5a1c7f0051ae3385608bc4Nick Pelly         */
2269439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
2279439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        /* response code , and header are ignored
2289439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly         * */
2299439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
2309439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        synchronized (this) {
23141557e18fa3fc5791a5a1c7f0051ae3385608bc4Nick Pelly            mObexConnected = false;
23241557e18fa3fc5791a5a1c7f0051ae3385608bc4Nick Pelly            setRequestInactive();
2339439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        }
2349439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
2359439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        return returnHeaderSet;
2369439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    }
2379439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
2389439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    public long getConnectionID() {
2399439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
24041557e18fa3fc5791a5a1c7f0051ae3385608bc4Nick Pelly        if (mConnectionId == null) {
2419439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            return -1;
2429439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        }
24341557e18fa3fc5791a5a1c7f0051ae3385608bc4Nick Pelly        return ObexHelper.convertToLong(mConnectionId);
2449439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    }
2459439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
24641557e18fa3fc5791a5a1c7f0051ae3385608bc4Nick Pelly    public Operation put(HeaderSet header) throws IOException {
24741557e18fa3fc5791a5a1c7f0051ae3385608bc4Nick Pelly        if (!mObexConnected) {
2489439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            throw new IOException("Not connected to the server");
2499439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        }
25041557e18fa3fc5791a5a1c7f0051ae3385608bc4Nick Pelly        setRequestActive();
2519439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
2529439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        ensureOpen();
2533998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun        HeaderSet head;
2549439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        if (header == null) {
2553998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun            head = new HeaderSet();
2569439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        } else {
2573998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun            head = header;
2583998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun            // when auth is initiated by client ,save the digest
2593998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun            if (head.nonce != null) {
26041557e18fa3fc5791a5a1c7f0051ae3385608bc4Nick Pelly                mChallengeDigest = new byte[16];
2613998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun                System.arraycopy(head.nonce, 0, mChallengeDigest, 0, 16);
2629439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            }
2639439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        }
2649439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
2659439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        // Add the connection ID if one exists
26641557e18fa3fc5791a5a1c7f0051ae3385608bc4Nick Pelly        if (mConnectionId != null) {
2679439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
2683998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun            head.mConnectionID = new byte[4];
2693998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun            System.arraycopy(mConnectionId, 0, head.mConnectionID, 0, 4);
2709439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        }
2719439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
2723998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun        return new ClientOperation(maxPacketSize, this, head, false);
2739439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    }
2749439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
2753998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun    public void setAuthenticator(Authenticator auth) throws IOException {
2769439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        if (auth == null) {
2773998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun            throw new IOException("Authenticator may not be null");
2789439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        }
27941557e18fa3fc5791a5a1c7f0051ae3385608bc4Nick Pelly        mAuthenticator = auth;
2809439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    }
2819439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
2823998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun    public HeaderSet setPath(HeaderSet header, boolean backup, boolean create) throws IOException {
28341557e18fa3fc5791a5a1c7f0051ae3385608bc4Nick Pelly        if (!mObexConnected) {
2849439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            throw new IOException("Not connected to the server");
2859439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        }
28641557e18fa3fc5791a5a1c7f0051ae3385608bc4Nick Pelly        setRequestActive();
2879439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        ensureOpen();
2889439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
2899439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        int totalLength = 2;
2909439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        byte[] head = null;
2913998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun        HeaderSet headset;
2929439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        if (header == null) {
2933998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun            headset = new HeaderSet();
2949439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        } else {
2953998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun            headset = header;
2963998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun            if (headset.nonce != null) {
29741557e18fa3fc5791a5a1c7f0051ae3385608bc4Nick Pelly                mChallengeDigest = new byte[16];
2983998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun                System.arraycopy(headset.nonce, 0, mChallengeDigest, 0, 16);
2999439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            }
3009439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        }
3019439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
3029439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        // when auth is initiated by client ,save the digest
3033998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun        if (headset.nonce != null) {
30441557e18fa3fc5791a5a1c7f0051ae3385608bc4Nick Pelly            mChallengeDigest = new byte[16];
3053998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun            System.arraycopy(headset.nonce, 0, mChallengeDigest, 0, 16);
3069439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        }
3079439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
3089439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        // Add the connection ID if one exists
30941557e18fa3fc5791a5a1c7f0051ae3385608bc4Nick Pelly        if (mConnectionId != null) {
3103998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun            headset.mConnectionID = new byte[4];
3113998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun            System.arraycopy(mConnectionId, 0, headset.mConnectionID, 0, 4);
3129439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        }
3139439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
3143998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun        head = ObexHelper.createHeader(headset, false);
3159439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        totalLength += head.length;
3169439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
3179439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        if (totalLength > maxPacketSize) {
3189439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            throw new IOException("Packet size exceeds max packet size");
3199439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        }
3209439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
3219439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        int flags = 0;
3229439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        /*
3239439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly         * The backup flag bit is bit 0 so if we add 1, this will set that bit
3249439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly         */
3259439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        if (backup) {
3269439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            flags++;
3279439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        }
3289439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        /*
3299439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly         * The create bit is bit 1 so if we or with 2 the bit will be set.
3309439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly         */
3319439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        if (!create) {
3329439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            flags |= 2;
3339439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        }
3349439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
3359439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        /*
3369439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly         * An OBEX SETPATH packet to the server:
3379439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly         * Byte 1: 0x85
3389439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly         * Byte 2 & 3: packet size
3399439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly         * Byte 4: flags
3409439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly         * Byte 5: constants
3419439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly         * Byte 6 & up: headers
3429439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly         */
3439439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        byte[] packet = new byte[totalLength];
3449439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        packet[0] = (byte)flags;
3459439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        packet[1] = (byte)0x00;
3463998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun        if (headset != null) {
3479439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            System.arraycopy(head, 0, packet, 2, head.length);
3489439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        }
3499439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
3509439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        HeaderSet returnHeaderSet = new HeaderSet();
3513998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun        sendRequest(ObexHelper.OBEX_OPCODE_SETPATH, packet, returnHeaderSet, null);
3529439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
3539439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        /*
3549439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly         * An OBEX SETPATH reply from the server:
3559439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly         * Byte 1: Response code
3569439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly         * Bytes 2 & 3: packet size
3579439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly         * Bytes 4 & up: headers
3589439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly         */
3599439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
36041557e18fa3fc5791a5a1c7f0051ae3385608bc4Nick Pelly        setRequestInactive();
3619439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
3629439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        return returnHeaderSet;
3639439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    }
3649439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
3659439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    /**
3669439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     * Verifies that the connection is open.
3672e0da96e757a977154063f980d3f4e1abd41cf09Nick Pelly     * @throws IOException if the connection is closed
3689439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     */
3699439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    public synchronized void ensureOpen() throws IOException {
37041557e18fa3fc5791a5a1c7f0051ae3385608bc4Nick Pelly        if (!mOpen) {
3719439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            throw new IOException("Connection closed");
3729439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        }
3739439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    }
3749439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
3759439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    /**
37605ff98bbefda39b9ff26f8bca132cfd0248745c6Tao Liejun     * Set request inactive. Allows Put and get operation objects to tell this
37705ff98bbefda39b9ff26f8bca132cfd0248745c6Tao Liejun     * object when they are done.
3789439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     */
3793998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun    /*package*/synchronized void setRequestInactive() {
38041557e18fa3fc5791a5a1c7f0051ae3385608bc4Nick Pelly        mRequestActive = false;
38141557e18fa3fc5791a5a1c7f0051ae3385608bc4Nick Pelly    }
38241557e18fa3fc5791a5a1c7f0051ae3385608bc4Nick Pelly
38341557e18fa3fc5791a5a1c7f0051ae3385608bc4Nick Pelly    /**
38441557e18fa3fc5791a5a1c7f0051ae3385608bc4Nick Pelly     * Set request to active.
38541557e18fa3fc5791a5a1c7f0051ae3385608bc4Nick Pelly     * @throws IOException if already active
38641557e18fa3fc5791a5a1c7f0051ae3385608bc4Nick Pelly     */
38741557e18fa3fc5791a5a1c7f0051ae3385608bc4Nick Pelly    private synchronized void setRequestActive() throws IOException {
38841557e18fa3fc5791a5a1c7f0051ae3385608bc4Nick Pelly        if (mRequestActive) {
38941557e18fa3fc5791a5a1c7f0051ae3385608bc4Nick Pelly            throw new IOException("OBEX request is already being performed");
3909439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        }
39141557e18fa3fc5791a5a1c7f0051ae3385608bc4Nick Pelly        mRequestActive = true;
3929439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    }
3939439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
3949439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    /**
39505ff98bbefda39b9ff26f8bca132cfd0248745c6Tao Liejun     * Sends a standard request to the client. It will then wait for the reply
39605ff98bbefda39b9ff26f8bca132cfd0248745c6Tao Liejun     * and update the header set object provided. If any authentication headers
39705ff98bbefda39b9ff26f8bca132cfd0248745c6Tao Liejun     * (i.e. authentication challenge or authentication response) are received,
39805ff98bbefda39b9ff26f8bca132cfd0248745c6Tao Liejun     * they will be processed.
3993998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun     * @param opCode the type of request to send to the client
40005ff98bbefda39b9ff26f8bca132cfd0248745c6Tao Liejun     * @param head the headers to send to the client
40141557e18fa3fc5791a5a1c7f0051ae3385608bc4Nick Pelly     * @param header the header object to update with the response
40205ff98bbefda39b9ff26f8bca132cfd0248745c6Tao Liejun     * @param privateInput the input stream used by the Operation object; null
40305ff98bbefda39b9ff26f8bca132cfd0248745c6Tao Liejun     *        if this is called on a CONNECT, SETPATH or DISCONNECT return
40405ff98bbefda39b9ff26f8bca132cfd0248745c6Tao Liejun     *        <code>true</code> if the operation completed successfully;
40505ff98bbefda39b9ff26f8bca132cfd0248745c6Tao Liejun     *        <code>false</code> if an authentication response failed to pass
4062e0da96e757a977154063f980d3f4e1abd41cf09Nick Pelly     * @throws IOException if an IO error occurs
4079439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     */
4083998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun    public boolean sendRequest(int opCode, byte[] head, HeaderSet header,
4099439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            PrivateInputStream privateInput) throws IOException {
4109439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        //check header length with local max size
4119439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        if (head != null) {
4122e0da96e757a977154063f980d3f4e1abd41cf09Nick Pelly            if ((head.length + 3) > ObexHelper.MAX_PACKET_SIZE_INT) {
4139439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                throw new IOException("header too large ");
4149439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            }
4159439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        }
4163998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun
4179439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        int bytesReceived;
4189439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        ByteArrayOutputStream out = new ByteArrayOutputStream();
4193998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun        out.write((byte)opCode);
4209439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
4219439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        // Determine if there are any headers to send
4229439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        if (head == null) {
4239439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            out.write(0x00);
4249439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            out.write(0x03);
4259439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        } else {
4269439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            out.write((byte)((head.length + 3) >> 8));
4279439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            out.write((byte)(head.length + 3));
4289439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            out.write(head);
4299439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        }
4309439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
4319439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        // Write the request to the output stream and flush the stream
43241557e18fa3fc5791a5a1c7f0051ae3385608bc4Nick Pelly        mOutput.write(out.toByteArray());
43341557e18fa3fc5791a5a1c7f0051ae3385608bc4Nick Pelly        mOutput.flush();
4349439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
43541557e18fa3fc5791a5a1c7f0051ae3385608bc4Nick Pelly        header.responseCode = mInput.read();
4369439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
43741557e18fa3fc5791a5a1c7f0051ae3385608bc4Nick Pelly        int length = ((mInput.read() << 8) | (mInput.read()));
4389439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
4392e0da96e757a977154063f980d3f4e1abd41cf09Nick Pelly        if (length > ObexHelper.MAX_PACKET_SIZE_INT) {
4409439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            throw new IOException("Packet received exceeds packet size limit");
4419439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        }
4423998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun        if (length > ObexHelper.BASE_PACKET_LENGTH) {
4439439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            byte[] data = null;
4443998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun            if (opCode == ObexHelper.OBEX_OPCODE_CONNECT) {
4453998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun                @SuppressWarnings("unused")
44641557e18fa3fc5791a5a1c7f0051ae3385608bc4Nick Pelly                int version = mInput.read();
4473998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun                @SuppressWarnings("unused")
44841557e18fa3fc5791a5a1c7f0051ae3385608bc4Nick Pelly                int flags = mInput.read();
44941557e18fa3fc5791a5a1c7f0051ae3385608bc4Nick Pelly                maxPacketSize = (mInput.read() << 8) + mInput.read();
4509439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
4519439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                //check with local max size
452e83b744d7d0b3caaf8f5456b795331d5db2495a3Erik Ljungberg                if (maxPacketSize > ObexHelper.MAX_CLIENT_PACKET_SIZE) {
453e83b744d7d0b3caaf8f5456b795331d5db2495a3Erik Ljungberg                    maxPacketSize = ObexHelper.MAX_CLIENT_PACKET_SIZE;
4549439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                }
4559439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
4569439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                if (length > 7) {
4579439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                    data = new byte[length - 7];
4589439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
45941557e18fa3fc5791a5a1c7f0051ae3385608bc4Nick Pelly                    bytesReceived = mInput.read(data);
4609439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                    while (bytesReceived != (length - 7)) {
46141557e18fa3fc5791a5a1c7f0051ae3385608bc4Nick Pelly                        bytesReceived += mInput.read(data, bytesReceived, data.length
4629439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                                - bytesReceived);
4639439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                    }
4649439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                } else {
4659439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                    return true;
4669439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                }
4679439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            } else {
4689439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                data = new byte[length - 3];
46941557e18fa3fc5791a5a1c7f0051ae3385608bc4Nick Pelly                bytesReceived = mInput.read(data);
4709439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
4719439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                while (bytesReceived != (length - 3)) {
47241557e18fa3fc5791a5a1c7f0051ae3385608bc4Nick Pelly                    bytesReceived += mInput.read(data, bytesReceived, data.length - bytesReceived);
4739439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                }
4743998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun                if (opCode == ObexHelper.OBEX_OPCODE_ABORT) {
4759439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                    return true;
4769439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                }
4779439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            }
4789439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
47941557e18fa3fc5791a5a1c7f0051ae3385608bc4Nick Pelly            byte[] body = ObexHelper.updateHeaderSet(header, data);
4809439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            if ((privateInput != null) && (body != null)) {
4819439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                privateInput.writeBytes(body, 1);
4829439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            }
4839439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
4843998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun            if (header.mConnectionID != null) {
48541557e18fa3fc5791a5a1c7f0051ae3385608bc4Nick Pelly                mConnectionId = new byte[4];
4863998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun                System.arraycopy(header.mConnectionID, 0, mConnectionId, 0, 4);
4879439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            }
4889439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
4893998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun            if (header.mAuthResp != null) {
4903998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun                if (!handleAuthResp(header.mAuthResp)) {
49141557e18fa3fc5791a5a1c7f0051ae3385608bc4Nick Pelly                    setRequestInactive();
4929439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                    throw new IOException("Authentication Failed");
4939439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                }
4949439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            }
4959439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
49641557e18fa3fc5791a5a1c7f0051ae3385608bc4Nick Pelly            if ((header.responseCode == ResponseCodes.OBEX_HTTP_UNAUTHORIZED)
4973998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun                    && (header.mAuthChall != null)) {
4989439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
49941557e18fa3fc5791a5a1c7f0051ae3385608bc4Nick Pelly                if (handleAuthChall(header)) {
5003998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun                    out.write((byte)HeaderSet.AUTH_RESPONSE);
5013998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun                    out.write((byte)((header.mAuthResp.length + 3) >> 8));
5023998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun                    out.write((byte)(header.mAuthResp.length + 3));
5033998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun                    out.write(header.mAuthResp);
5043998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun                    header.mAuthChall = null;
5053998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun                    header.mAuthResp = null;
5069439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
5079439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                    byte[] sendHeaders = new byte[out.size() - 3];
5089439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                    System.arraycopy(out.toByteArray(), 3, sendHeaders, 0, sendHeaders.length);
5099439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
5103998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun                    return sendRequest(opCode, sendHeaders, header, privateInput);
5119439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                }
5129439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            }
5139439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        }
5149439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
5159439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        return true;
5169439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    }
5179439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
5189439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    public void close() throws IOException {
51941557e18fa3fc5791a5a1c7f0051ae3385608bc4Nick Pelly        mOpen = false;
52041557e18fa3fc5791a5a1c7f0051ae3385608bc4Nick Pelly        mInput.close();
52141557e18fa3fc5791a5a1c7f0051ae3385608bc4Nick Pelly        mOutput.close();
5229439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    }
5239439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly}
524