1 /* 2 * Copyright (c) 2008-2009, Motorola, Inc. 3 * 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions are met: 8 * 9 * - Redistributions of source code must retain the above copyright notice, 10 * this list of conditions and the following disclaimer. 11 * 12 * - Redistributions in binary form must reproduce the above copyright notice, 13 * this list of conditions and the following disclaimer in the documentation 14 * and/or other materials provided with the distribution. 15 * 16 * - Neither the name of the Motorola, Inc. nor the names of its contributors 17 * may be used to endorse or promote products derived from this software 18 * without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 24 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 30 * POSSIBILITY OF SUCH DAMAGE. 31 */ 32 33 package javax.obex; 34 35 import android.util.Log; 36 37 import java.io.InputStream; 38 import java.io.IOException; 39 import java.io.OutputStream; 40 41 /** 42 * This class in an implementation of the OBEX ServerSession. 43 * @hide 44 */ 45 public final class ServerSession extends ObexSession implements Runnable { 46 47 private static final String TAG = "Obex ServerSession"; 48 49 private ObexTransport mTransport; 50 51 private InputStream mInput; 52 53 private OutputStream mOutput; 54 55 private ServerRequestHandler mListener; 56 57 private Thread mProcessThread; 58 59 private int mMaxPacketLength; 60 61 private boolean mClosed; 62 63 /** 64 * Creates new ServerSession. 65 * @param trans the connection to the client 66 * @param handler the event listener that will process requests 67 * @param auth the authenticator to use with this connection 68 * @throws IOException if an error occurred while opening the input and 69 * output streams 70 */ 71 public ServerSession(ObexTransport trans, ServerRequestHandler handler, Authenticator auth) 72 throws IOException { 73 mAuthenticator = auth; 74 mTransport = trans; 75 mInput = mTransport.openInputStream(); 76 mOutput = mTransport.openOutputStream(); 77 mListener = handler; 78 mMaxPacketLength = 256; 79 80 mClosed = false; 81 mProcessThread = new Thread(this); 82 mProcessThread.start(); 83 } 84 85 /** 86 * Processes requests made to the server and forwards them to the 87 * appropriate event listener. 88 */ 89 public void run() { 90 try { 91 92 boolean done = false; 93 while (!done && !mClosed) { 94 int requestType = mInput.read(); 95 switch (requestType) { 96 case ObexHelper.OBEX_OPCODE_CONNECT: 97 handleConnectRequest(); 98 break; 99 100 case ObexHelper.OBEX_OPCODE_DISCONNECT: 101 handleDisconnectRequest(); 102 done = true; 103 break; 104 105 case ObexHelper.OBEX_OPCODE_GET: 106 case ObexHelper.OBEX_OPCODE_GET_FINAL: 107 handleGetRequest(requestType); 108 break; 109 110 case ObexHelper.OBEX_OPCODE_PUT: 111 case ObexHelper.OBEX_OPCODE_PUT_FINAL: 112 handlePutRequest(requestType); 113 break; 114 115 case ObexHelper.OBEX_OPCODE_SETPATH: 116 handleSetPathRequest(); 117 break; 118 case ObexHelper.OBEX_OPCODE_ABORT: 119 handleAbortRequest(); 120 break; 121 122 case -1: 123 done = true; 124 break; 125 126 default: 127 128 /* 129 * Received a request type that is not recognized so I am 130 * just going to read the packet and send a not implemented 131 * to the client 132 */ 133 int length = mInput.read(); 134 length = (length << 8) + mInput.read(); 135 for (int i = 3; i < length; i++) { 136 mInput.read(); 137 } 138 sendResponse(ResponseCodes.OBEX_HTTP_NOT_IMPLEMENTED, null); 139 } 140 } 141 142 } catch (NullPointerException e) { 143 Log.d(TAG, e.toString()); 144 } catch (Exception e) { 145 Log.d(TAG, e.toString()); 146 } 147 close(); 148 } 149 150 /** 151 * Handles a ABORT request from a client. This method will read the rest of 152 * the request from the client. Assuming the request is valid, it will 153 * create a <code>HeaderSet</code> object to pass to the 154 * <code>ServerRequestHandler</code> object. After the handler processes the 155 * request, this method will create a reply message to send to the server. 156 * 157 * @throws IOException if an error occurred at the transport layer 158 */ 159 private void handleAbortRequest() throws IOException { 160 int code = ResponseCodes.OBEX_HTTP_OK; 161 HeaderSet request = new HeaderSet(); 162 HeaderSet reply = new HeaderSet(); 163 164 int length = mInput.read(); 165 length = (length << 8) + mInput.read(); 166 if (length > ObexHelper.MAX_PACKET_SIZE_INT) { 167 code = ResponseCodes.OBEX_HTTP_REQ_TOO_LARGE; 168 } else { 169 for (int i = 3; i < length; i++) { 170 mInput.read(); 171 } 172 code = mListener.onAbort(request, reply); 173 Log.v(TAG, "onAbort request handler return value- " + code); 174 code = validateResponseCode(code); 175 } 176 sendResponse(code, null); 177 } 178 179 /** 180 * Handles a PUT request from a client. This method will provide a 181 * <code>ServerOperation</code> object to the request handler. The 182 * <code>ServerOperation</code> object will handle the rest of the request. 183 * It will also send replies and receive requests until the final reply 184 * should be sent. When the final reply should be sent, this method will get 185 * the response code to use and send the reply. The 186 * <code>ServerOperation</code> object will always reply with a 187 * OBEX_HTTP_CONTINUE reply. It will only reply if further information is 188 * needed. 189 * @param type the type of request received; either 0x02 or 0x82 190 * @throws IOException if an error occurred at the transport layer 191 */ 192 private void handlePutRequest(int type) throws IOException { 193 ServerOperation op = new ServerOperation(this, mInput, type, mMaxPacketLength, mListener); 194 try { 195 int response = -1; 196 197 if ((op.finalBitSet) && !op.isValidBody()) { 198 response = validateResponseCode(mListener 199 .onDelete(op.requestHeader, op.replyHeader)); 200 } else { 201 response = validateResponseCode(mListener.onPut(op)); 202 } 203 if (response != ResponseCodes.OBEX_HTTP_OK && !op.isAborted) { 204 op.sendReply(response); 205 } else if (!op.isAborted) { 206 // wait for the final bit 207 while (!op.finalBitSet) { 208 op.sendReply(ResponseCodes.OBEX_HTTP_CONTINUE); 209 } 210 op.sendReply(response); 211 } 212 } catch (Exception e) { 213 /*To fix bugs in aborted cases, 214 *(client abort file transfer prior to the last packet which has the end of body header, 215 *internal error should not be sent because server has already replied with 216 *OK response in "sendReply") 217 */ 218 if (!op.isAborted) { 219 sendResponse(ResponseCodes.OBEX_HTTP_INTERNAL_ERROR, null); 220 } 221 } 222 } 223 224 /** 225 * Handles a GET request from a client. This method will provide a 226 * <code>ServerOperation</code> object to the request handler. The 227 * <code>ServerOperation</code> object will handle the rest of the request. 228 * It will also send replies and receive requests until the final reply 229 * should be sent. When the final reply should be sent, this method will get 230 * the response code to use and send the reply. The 231 * <code>ServerOperation</code> object will always reply with a 232 * OBEX_HTTP_CONTINUE reply. It will only reply if further information is 233 * needed. 234 * @param type the type of request received; either 0x03 or 0x83 235 * @throws IOException if an error occurred at the transport layer 236 */ 237 private void handleGetRequest(int type) throws IOException { 238 ServerOperation op = new ServerOperation(this, mInput, type, mMaxPacketLength, mListener); 239 try { 240 int response = validateResponseCode(mListener.onGet(op)); 241 242 if (!op.isAborted) { 243 op.sendReply(response); 244 } 245 } catch (Exception e) { 246 sendResponse(ResponseCodes.OBEX_HTTP_INTERNAL_ERROR, null); 247 } 248 } 249 250 /** 251 * Send standard response. 252 * @param code the response code to send 253 * @param header the headers to include in the response 254 * @throws IOException if an IO error occurs 255 */ 256 public void sendResponse(int code, byte[] header) throws IOException { 257 int totalLength = 3; 258 byte[] data = null; 259 260 if (header != null) { 261 totalLength += header.length; 262 data = new byte[totalLength]; 263 data[0] = (byte)code; 264 data[1] = (byte)(totalLength >> 8); 265 data[2] = (byte)totalLength; 266 System.arraycopy(header, 0, data, 3, header.length); 267 } else { 268 data = new byte[totalLength]; 269 data[0] = (byte)code; 270 data[1] = (byte)0x00; 271 data[2] = (byte)totalLength; 272 } 273 mOutput.write(data); 274 mOutput.flush(); 275 } 276 277 /** 278 * Handles a SETPATH request from a client. This method will read the rest 279 * of the request from the client. Assuming the request is valid, it will 280 * create a <code>HeaderSet</code> object to pass to the 281 * <code>ServerRequestHandler</code> object. After the handler processes the 282 * request, this method will create a reply message to send to the server 283 * with the response code provided. 284 * @throws IOException if an error occurred at the transport layer 285 */ 286 private void handleSetPathRequest() throws IOException { 287 int length; 288 int flags; 289 @SuppressWarnings("unused") 290 int constants; 291 int totalLength = 3; 292 byte[] head = null; 293 int code = -1; 294 int bytesReceived; 295 HeaderSet request = new HeaderSet(); 296 HeaderSet reply = new HeaderSet(); 297 298 length = mInput.read(); 299 length = (length << 8) + mInput.read(); 300 flags = mInput.read(); 301 constants = mInput.read(); 302 303 if (length > ObexHelper.MAX_PACKET_SIZE_INT) { 304 code = ResponseCodes.OBEX_HTTP_REQ_TOO_LARGE; 305 totalLength = 3; 306 } else { 307 if (length > 5) { 308 byte[] headers = new byte[length - 5]; 309 bytesReceived = mInput.read(headers); 310 311 while (bytesReceived != headers.length) { 312 bytesReceived += mInput.read(headers, bytesReceived, headers.length 313 - bytesReceived); 314 } 315 316 ObexHelper.updateHeaderSet(request, headers); 317 318 if (mListener.getConnectionId() != -1 && request.mConnectionID != null) { 319 mListener.setConnectionId(ObexHelper.convertToLong(request.mConnectionID)); 320 } else { 321 mListener.setConnectionId(1); 322 } 323 // the Auth chan is initiated by the server, client sent back the authResp . 324 if (request.mAuthResp != null) { 325 if (!handleAuthResp(request.mAuthResp)) { 326 code = ResponseCodes.OBEX_HTTP_UNAUTHORIZED; 327 mListener.onAuthenticationFailure(ObexHelper.getTagValue((byte)0x01, 328 request.mAuthResp)); 329 } 330 request.mAuthResp = null; 331 } 332 } 333 334 if (code != ResponseCodes.OBEX_HTTP_UNAUTHORIZED) { 335 // the Auth challenge is initiated by the client 336 // the server will send back the authResp to the client 337 if (request.mAuthChall != null) { 338 handleAuthChall(request); 339 reply.mAuthResp = new byte[request.mAuthResp.length]; 340 System.arraycopy(request.mAuthResp, 0, reply.mAuthResp, 0, 341 reply.mAuthResp.length); 342 request.mAuthChall = null; 343 request.mAuthResp = null; 344 } 345 boolean backup = false; 346 boolean create = true; 347 if (!((flags & 1) == 0)) { 348 backup = true; 349 } 350 if (!((flags & 2) == 0)) { 351 create = false; 352 } 353 354 try { 355 code = mListener.onSetPath(request, reply, backup, create); 356 } catch (Exception e) { 357 sendResponse(ResponseCodes.OBEX_HTTP_INTERNAL_ERROR, null); 358 return; 359 } 360 361 code = validateResponseCode(code); 362 363 if (reply.nonce != null) { 364 mChallengeDigest = new byte[16]; 365 System.arraycopy(reply.nonce, 0, mChallengeDigest, 0, 16); 366 } else { 367 mChallengeDigest = null; 368 } 369 370 long id = mListener.getConnectionId(); 371 if (id == -1) { 372 reply.mConnectionID = null; 373 } else { 374 reply.mConnectionID = ObexHelper.convertToByteArray(id); 375 } 376 377 head = ObexHelper.createHeader(reply, false); 378 totalLength += head.length; 379 380 if (totalLength > mMaxPacketLength) { 381 totalLength = 3; 382 head = null; 383 code = ResponseCodes.OBEX_HTTP_INTERNAL_ERROR; 384 } 385 } 386 } 387 388 // Compute Length of OBEX SETPATH packet 389 byte[] replyData = new byte[totalLength]; 390 replyData[0] = (byte)code; 391 replyData[1] = (byte)(totalLength >> 8); 392 replyData[2] = (byte)totalLength; 393 if (head != null) { 394 System.arraycopy(head, 0, replyData, 3, head.length); 395 } 396 /* 397 * Write the OBEX SETPATH packet to the server. Byte 0: response code 398 * Byte 1&2: Connect Packet Length Byte 3 to n: headers 399 */ 400 mOutput.write(replyData); 401 mOutput.flush(); 402 } 403 404 /** 405 * Handles a disconnect request from a client. This method will read the 406 * rest of the request from the client. Assuming the request is valid, it 407 * will create a <code>HeaderSet</code> object to pass to the 408 * <code>ServerRequestHandler</code> object. After the handler processes the 409 * request, this method will create a reply message to send to the server. 410 * @throws IOException if an error occurred at the transport layer 411 */ 412 private void handleDisconnectRequest() throws IOException { 413 int length; 414 int code = ResponseCodes.OBEX_HTTP_OK; 415 int totalLength = 3; 416 byte[] head = null; 417 int bytesReceived; 418 HeaderSet request = new HeaderSet(); 419 HeaderSet reply = new HeaderSet(); 420 421 length = mInput.read(); 422 length = (length << 8) + mInput.read(); 423 424 if (length > ObexHelper.MAX_PACKET_SIZE_INT) { 425 code = ResponseCodes.OBEX_HTTP_REQ_TOO_LARGE; 426 totalLength = 3; 427 } else { 428 if (length > 3) { 429 byte[] headers = new byte[length - 3]; 430 bytesReceived = mInput.read(headers); 431 432 while (bytesReceived != headers.length) { 433 bytesReceived += mInput.read(headers, bytesReceived, headers.length 434 - bytesReceived); 435 } 436 437 ObexHelper.updateHeaderSet(request, headers); 438 } 439 440 if (mListener.getConnectionId() != -1 && request.mConnectionID != null) { 441 mListener.setConnectionId(ObexHelper.convertToLong(request.mConnectionID)); 442 } else { 443 mListener.setConnectionId(1); 444 } 445 446 if (request.mAuthResp != null) { 447 if (!handleAuthResp(request.mAuthResp)) { 448 code = ResponseCodes.OBEX_HTTP_UNAUTHORIZED; 449 mListener.onAuthenticationFailure(ObexHelper.getTagValue((byte)0x01, 450 request.mAuthResp)); 451 } 452 request.mAuthResp = null; 453 } 454 455 if (code != ResponseCodes.OBEX_HTTP_UNAUTHORIZED) { 456 457 if (request.mAuthChall != null) { 458 handleAuthChall(request); 459 request.mAuthChall = null; 460 } 461 462 try { 463 mListener.onDisconnect(request, reply); 464 } catch (Exception e) { 465 sendResponse(ResponseCodes.OBEX_HTTP_INTERNAL_ERROR, null); 466 return; 467 } 468 469 long id = mListener.getConnectionId(); 470 if (id == -1) { 471 reply.mConnectionID = null; 472 } else { 473 reply.mConnectionID = ObexHelper.convertToByteArray(id); 474 } 475 476 head = ObexHelper.createHeader(reply, false); 477 totalLength += head.length; 478 479 if (totalLength > mMaxPacketLength) { 480 totalLength = 3; 481 head = null; 482 code = ResponseCodes.OBEX_HTTP_INTERNAL_ERROR; 483 } 484 } 485 } 486 487 // Compute Length of OBEX CONNECT packet 488 byte[] replyData; 489 if (head != null) { 490 replyData = new byte[3 + head.length]; 491 } else { 492 replyData = new byte[3]; 493 } 494 replyData[0] = (byte)code; 495 replyData[1] = (byte)(totalLength >> 8); 496 replyData[2] = (byte)totalLength; 497 if (head != null) { 498 System.arraycopy(head, 0, replyData, 3, head.length); 499 } 500 /* 501 * Write the OBEX DISCONNECT packet to the server. Byte 0: response code 502 * Byte 1&2: Connect Packet Length Byte 3 to n: headers 503 */ 504 mOutput.write(replyData); 505 mOutput.flush(); 506 } 507 508 /** 509 * Handles a connect request from a client. This method will read the rest 510 * of the request from the client. Assuming the request is valid, it will 511 * create a <code>HeaderSet</code> object to pass to the 512 * <code>ServerRequestHandler</code> object. After the handler processes the 513 * request, this method will create a reply message to send to the server 514 * with the response code provided. 515 * @throws IOException if an error occurred at the transport layer 516 */ 517 private void handleConnectRequest() throws IOException { 518 int packetLength; 519 @SuppressWarnings("unused") 520 int version; 521 @SuppressWarnings("unused") 522 int flags; 523 int totalLength = 7; 524 byte[] head = null; 525 int code = -1; 526 HeaderSet request = new HeaderSet(); 527 HeaderSet reply = new HeaderSet(); 528 int bytesReceived; 529 530 /* 531 * Read in the length of the OBEX packet, OBEX version, flags, and max 532 * packet length 533 */ 534 packetLength = mInput.read(); 535 packetLength = (packetLength << 8) + mInput.read(); 536 version = mInput.read(); 537 flags = mInput.read(); 538 mMaxPacketLength = mInput.read(); 539 mMaxPacketLength = (mMaxPacketLength << 8) + mInput.read(); 540 541 // should we check it? 542 if (mMaxPacketLength > ObexHelper.MAX_PACKET_SIZE_INT) { 543 mMaxPacketLength = ObexHelper.MAX_PACKET_SIZE_INT; 544 } 545 546 if (packetLength > ObexHelper.MAX_PACKET_SIZE_INT) { 547 code = ResponseCodes.OBEX_HTTP_REQ_TOO_LARGE; 548 totalLength = 7; 549 } else { 550 if (packetLength > 7) { 551 byte[] headers = new byte[packetLength - 7]; 552 bytesReceived = mInput.read(headers); 553 554 while (bytesReceived != headers.length) { 555 bytesReceived += mInput.read(headers, bytesReceived, headers.length 556 - bytesReceived); 557 } 558 559 ObexHelper.updateHeaderSet(request, headers); 560 } 561 562 if (mListener.getConnectionId() != -1 && request.mConnectionID != null) { 563 mListener.setConnectionId(ObexHelper.convertToLong(request.mConnectionID)); 564 } else { 565 mListener.setConnectionId(1); 566 } 567 568 if (request.mAuthResp != null) { 569 if (!handleAuthResp(request.mAuthResp)) { 570 code = ResponseCodes.OBEX_HTTP_UNAUTHORIZED; 571 mListener.onAuthenticationFailure(ObexHelper.getTagValue((byte)0x01, 572 request.mAuthResp)); 573 } 574 request.mAuthResp = null; 575 } 576 577 if (code != ResponseCodes.OBEX_HTTP_UNAUTHORIZED) { 578 if (request.mAuthChall != null) { 579 handleAuthChall(request); 580 reply.mAuthResp = new byte[request.mAuthResp.length]; 581 System.arraycopy(request.mAuthResp, 0, reply.mAuthResp, 0, 582 reply.mAuthResp.length); 583 request.mAuthChall = null; 584 request.mAuthResp = null; 585 } 586 587 try { 588 code = mListener.onConnect(request, reply); 589 code = validateResponseCode(code); 590 591 if (reply.nonce != null) { 592 mChallengeDigest = new byte[16]; 593 System.arraycopy(reply.nonce, 0, mChallengeDigest, 0, 16); 594 } else { 595 mChallengeDigest = null; 596 } 597 long id = mListener.getConnectionId(); 598 if (id == -1) { 599 reply.mConnectionID = null; 600 } else { 601 reply.mConnectionID = ObexHelper.convertToByteArray(id); 602 } 603 604 head = ObexHelper.createHeader(reply, false); 605 totalLength += head.length; 606 607 if (totalLength > mMaxPacketLength) { 608 totalLength = 7; 609 head = null; 610 code = ResponseCodes.OBEX_HTTP_INTERNAL_ERROR; 611 } 612 } catch (Exception e) { 613 e.printStackTrace(); 614 totalLength = 7; 615 head = null; 616 code = ResponseCodes.OBEX_HTTP_INTERNAL_ERROR; 617 } 618 619 } 620 } 621 622 // Compute Length of OBEX CONNECT packet 623 byte[] length = ObexHelper.convertToByteArray(totalLength); 624 625 /* 626 * Write the OBEX CONNECT packet to the server. Byte 0: response code 627 * Byte 1&2: Connect Packet Length Byte 3: OBEX Version Number 628 * (Presently, 0x10) Byte 4: Flags (For TCP 0x00) Byte 5&6: Max OBEX 629 * Packet Length (Defined in MAX_PACKET_SIZE) Byte 7 to n: headers 630 */ 631 byte[] sendData = new byte[totalLength]; 632 sendData[0] = (byte)code; 633 sendData[1] = length[2]; 634 sendData[2] = length[3]; 635 sendData[3] = (byte)0x10; 636 sendData[4] = (byte)0x00; 637 sendData[5] = (byte)(ObexHelper.MAX_PACKET_SIZE_INT >> 8); 638 sendData[6] = (byte)(ObexHelper.MAX_PACKET_SIZE_INT & 0xFF); 639 640 if (head != null) { 641 System.arraycopy(head, 0, sendData, 7, head.length); 642 } 643 644 mOutput.write(sendData); 645 mOutput.flush(); 646 } 647 648 /** 649 * Closes the server session - in detail close I/O streams and the 650 * underlying transport layer. Internal flag is also set so that later 651 * attempt to read/write will throw an exception. 652 */ 653 public synchronized void close() { 654 if (mListener != null) { 655 mListener.onClose(); 656 } 657 try { 658 mInput.close(); 659 mOutput.close(); 660 mTransport.close(); 661 mClosed = true; 662 } catch (Exception e) { 663 } 664 mTransport = null; 665 mInput = null; 666 mOutput = null; 667 mListener = null; 668 } 669 670 /** 671 * Verifies that the response code is valid. If it is not valid, it will 672 * return the <code>OBEX_HTTP_INTERNAL_ERROR</code> response code. 673 * @param code the response code to check 674 * @return the valid response code or <code>OBEX_HTTP_INTERNAL_ERROR</code> 675 * if <code>code</code> is not valid 676 */ 677 private int validateResponseCode(int code) { 678 679 if ((code >= ResponseCodes.OBEX_HTTP_OK) && (code <= ResponseCodes.OBEX_HTTP_PARTIAL)) { 680 return code; 681 } 682 if ((code >= ResponseCodes.OBEX_HTTP_MULT_CHOICE) 683 && (code <= ResponseCodes.OBEX_HTTP_USE_PROXY)) { 684 return code; 685 } 686 if ((code >= ResponseCodes.OBEX_HTTP_BAD_REQUEST) 687 && (code <= ResponseCodes.OBEX_HTTP_UNSUPPORTED_TYPE)) { 688 return code; 689 } 690 if ((code >= ResponseCodes.OBEX_HTTP_INTERNAL_ERROR) 691 && (code <= ResponseCodes.OBEX_HTTP_VERSION)) { 692 return code; 693 } 694 if ((code >= ResponseCodes.OBEX_DATABASE_FULL) 695 && (code <= ResponseCodes.OBEX_DATABASE_LOCKED)) { 696 return code; 697 } 698 return ResponseCodes.OBEX_HTTP_INTERNAL_ERROR; 699 } 700 701 } 702