content: /*
   * 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 <code>HeaderSet</code> object to pass to the
       * <code>ServerRequestHandler</code> 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
       * <code>ServerOperation</code> object to the request handler. The
       * <code>ServerOperation</code> 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
       * <code>ServerOperation</code> 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
       * <code>ServerOperation</code> object to the request handler. The
       * <code>ServerOperation</code> 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
       * <code>ServerOperation</code> 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 <code>HeaderSet</code> object to pass to the
       * <code>ServerRequestHandler</code> 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 <code>HeaderSet</code> object to pass to the
       * <code>ServerRequestHandler</code> 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 <code>HeaderSet</code> object to pass to the
       * <code>ServerRequestHandler</code> 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 <code>OBEX_HTTP_INTERNAL_ERROR</code> response code.
       * @param code the response code to check
       * @return the valid response code or <code>OBEX_HTTP_INTERNAL_ERROR</code>
       *         if <code>code</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;
      }
  }
  