• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2014 The Android Open Source Project
3  * Copyright (c) 2008-2009, Motorola, Inc.
4  *
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions are met:
9  *
10  * - Redistributions of source code must retain the above copyright notice,
11  * this list of conditions and the following disclaimer.
12  *
13  * - Redistributions in binary form must reproduce the above copyright notice,
14  * this list of conditions and the following disclaimer in the documentation
15  * and/or other materials provided with the distribution.
16  *
17  * - Neither the name of the Motorola, Inc. nor the names of its contributors
18  * may be used to endorse or promote products derived from this software
19  * without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
25  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31  * POSSIBILITY OF SUCH DAMAGE.
32  */
33 
34 package com.android.obex;
35 
36 import java.io.ByteArrayOutputStream;
37 import java.io.IOException;
38 import java.security.SecureRandom;
39 import java.util.Calendar;
40 
41 /**
42  * This class implements the com.android.obex.HeaderSet interface for OBEX over
43  * RFCOMM or OBEX over l2cap.
44  */
45 public final class HeaderSet {
46 
47     /**
48      * Represents the OBEX Count header. This allows the connection statement to
49      * tell the server how many objects it plans to send or retrieve.
50      * <P>
51      * The value of <code>COUNT</code> is 0xC0 (192).
52      */
53     public static final int COUNT = 0xC0;
54 
55     /**
56      * Represents the OBEX Name header. This specifies the name of the object.
57      * <P>
58      * The value of <code>NAME</code> is 0x01 (1).
59      */
60     public static final int NAME = 0x01;
61 
62     /**
63      * Represents the OBEX Type header. This allows a request to specify the
64      * type of the object (e.g. text, html, binary, etc.).
65      * <P>
66      * The value of <code>TYPE</code> is 0x42 (66).
67      */
68     public static final int TYPE = 0x42;
69 
70     /**
71      * Represents the OBEX Length header. This is the length of the object in
72      * bytes.
73      * <P>
74      * The value of <code>LENGTH</code> is 0xC3 (195).
75      */
76     public static final int LENGTH = 0xC3;
77 
78     /**
79      * Represents the OBEX Time header using the ISO 8601 standards. This is the
80      * preferred time header.
81      * <P>
82      * The value of <code>TIME_ISO_8601</code> is 0x44 (68).
83      */
84     public static final int TIME_ISO_8601 = 0x44;
85 
86     /**
87      * Represents the OBEX Time header using the 4 byte representation. This is
88      * only included for backwards compatibility. It represents the number of
89      * seconds since January 1, 1970.
90      * <P>
91      * The value of <code>TIME_4_BYTE</code> is 0xC4 (196).
92      */
93     public static final int TIME_4_BYTE = 0xC4;
94 
95     /**
96      * Represents the OBEX Description header. This is a text description of the
97      * object.
98      * <P>
99      * The value of <code>DESCRIPTION</code> is 0x05 (5).
100      */
101     public static final int DESCRIPTION = 0x05;
102 
103     /**
104      * Represents the OBEX Target header. This is the name of the service an
105      * operation is targeted to.
106      * <P>
107      * The value of <code>TARGET</code> is 0x46 (70).
108      */
109     public static final int TARGET = 0x46;
110 
111     /**
112      * Represents the OBEX HTTP header. This allows an HTTP 1.X header to be
113      * included in a request or reply.
114      * <P>
115      * The value of <code>HTTP</code> is 0x47 (71).
116      */
117     public static final int HTTP = 0x47;
118 
119     /**
120      * Represents the OBEX BODY header.
121      * <P>
122      * The value of <code>BODY</code> is 0x48 (72).
123      *
124      * @hide
125      */
126     public static final int BODY = 0x48;
127 
128     /**
129      * Represents the OBEX End of BODY header.
130      * <P>
131      * The value of <code>BODY</code> is 0x49 (73).
132      *
133      * @hide
134      */
135     public static final int END_OF_BODY = 0x49;
136 
137     /**
138      * Represents the OBEX Who header. Identifies the OBEX application to
139      * determine if the two peers are talking to each other.
140      * <P>
141      * The value of <code>WHO</code> is 0x4A (74).
142      */
143     public static final int WHO = 0x4A;
144 
145     /**
146      * Represents the OBEX Connection ID header. Identifies used for OBEX
147      * connection multiplexing.
148      * <P>
149      * The value of <code>CONNECTION_ID</code> is 0xCB (203).
150      *
151      * @hide
152      */
153     public static final int CONNECTION_ID = 0xCB;
154 
155     /**
156      * Represents the OBEX Application Parameter header. This header specifies
157      * additional application request and response information.
158      * <P>
159      * The value of <code>APPLICATION_PARAMETER</code> is 0x4C (76).
160      */
161     public static final int APPLICATION_PARAMETER = 0x4C;
162 
163     /**
164      * Represents the OBEX authentication digest-challenge.
165      * <P>
166      * The value of <code>AUTH_CHALLENGE</code> is 0x4D (77).
167      *
168      * @hide
169      */
170     public static final int AUTH_CHALLENGE = 0x4D;
171 
172     /**
173      * Represents the OBEX authentication digest-response.
174      * <P>
175      * The value of <code>AUTH_RESPONSE</code> is 0x4E (78).
176      *
177      * @hide
178      */
179     public static final int AUTH_RESPONSE = 0x4E;
180 
181     /**
182      * Represents the OBEX Object Class header. This header specifies the OBEX
183      * object class of the object.
184      * <P>
185      * The value of <code>OBJECT_CLASS</code> is 0x4F (79).
186      */
187     public static final int OBJECT_CLASS = 0x4F;
188 
189     /**
190      * Represents the OBEX Single Response Mode (SRM). This header is used
191      * for Single response mode, introduced in OBEX 1.5.
192      * <P>
193      * The value of <code>SINGLE_RESPONSE_MODE</code> is 0x97 (151).
194      *
195      * @hide
196      */
197     public static final int SINGLE_RESPONSE_MODE = 0x97;
198 
199     /**
200      * Represents the OBEX Single Response Mode Parameters. This header is used
201      * for Single response mode, introduced in OBEX 1.5.
202      * <P>
203      * The value of <code>SINGLE_RESPONSE_MODE_PARAMETER</code> is 0x98 (152).
204      *
205      * @hide
206      */
207     public static final int SINGLE_RESPONSE_MODE_PARAMETER = 0x98;
208 
209     private Long mCount; // 4 byte unsigned integer
210 
211     private String mName; // null terminated Unicode text string
212 
213     private boolean mEmptyName;
214 
215     private String mType; // null terminated ASCII text string
216 
217     private Long mLength; // 4 byte unsigend integer
218 
219     private Calendar mIsoTime; // String of the form YYYYMMDDTHHMMSSZ
220 
221     private Calendar mByteTime; // 4 byte unsigned integer
222 
223     private String mDescription; // null terminated Unicode text String
224 
225     private byte[] mTarget; // byte sequence
226 
227     private byte[] mHttpHeader; // byte sequence
228 
229     private byte[] mWho; // length prefixed byte sequence
230 
231     private byte[] mAppParam; // byte sequence of the form tag length value
232 
233     private byte[] mObjectClass; // byte sequence
234 
235     private String[] mUnicodeUserDefined; // null terminated unicode string
236 
237     private byte[][] mSequenceUserDefined; // byte sequence user defined
238 
239     private Byte[] mByteUserDefined; // 1 byte
240 
241     private Long[] mIntegerUserDefined; // 4 byte unsigned integer
242 
243     private SecureRandom mRandom = null;
244 
245     private Byte mSingleResponseMode; // byte to indicate enable/disable/support for SRM
246 
247     private Byte mSrmParam; // byte representing the SRM parameters - only "wait"
248                             // is supported by Bluetooth
249 
250     /*package*/ byte[] nonce;
251 
252     public byte[] mAuthChall; // The authentication challenge header
253 
254     public byte[] mAuthResp; // The authentication response header
255 
256     public byte[] mConnectionID; // THe connection ID
257 
258     public int responseCode;
259 
260     /**
261      * Creates new <code>HeaderSet</code> object.
262      */
HeaderSet()263     public HeaderSet() {
264         mUnicodeUserDefined = new String[16];
265         mSequenceUserDefined = new byte[16][];
266         mByteUserDefined = new Byte[16];
267         mIntegerUserDefined = new Long[16];
268         responseCode = -1;
269     }
270 
271     /**
272      * Sets flag for special "value" of NAME header which should be empty. This
273      * is not the same as NAME header with empty string in which case it will
274      * have length of 5 bytes. It should be 3 bytes with only header id and
275      * length field.
276      */
setEmptyNameHeader()277     public void setEmptyNameHeader() {
278         mName = null;
279         mEmptyName = true;
280     }
281 
282     /**
283      * Gets flag for special "value" of NAME header which should be empty. See
284      * above.
285      *
286      * @hide
287      */
getEmptyNameHeader()288     public boolean getEmptyNameHeader() {
289         return mEmptyName;
290     }
291 
292     /**
293      * Sets the value of the header identifier to the value provided. The type
294      * of object must correspond to the Java type defined in the description of
295      * this interface. If <code>null</code> is passed as the
296      * <code>headerValue</code> then the header will be removed from the set of
297      * headers to include in the next request.
298      * @param headerID the identifier to include in the message
299      * @param headerValue the value of the header identifier
300      * @throws IllegalArgumentException if the header identifier provided is not
301      *         one defined in this interface or a user-defined header; if the
302      *         type of <code>headerValue</code> is not the correct Java type as
303      *         defined in the description of this interface\
304      */
setHeader(int headerID, Object headerValue)305     public void setHeader(int headerID, Object headerValue) {
306         long temp = -1;
307 
308         switch (headerID) {
309             case COUNT:
310                 if (!(headerValue instanceof Long)) {
311                     if (headerValue == null) {
312                         mCount = null;
313                         break;
314                     }
315                     throw new IllegalArgumentException("Count must be a Long");
316                 }
317                 temp = ((Long)headerValue).longValue();
318                 if ((temp < 0L) || (temp > 0xFFFFFFFFL)) {
319                     throw new IllegalArgumentException("Count must be between 0 and 0xFFFFFFFF");
320                 }
321                 mCount = (Long)headerValue;
322                 break;
323             case NAME:
324                 if ((headerValue != null) && (!(headerValue instanceof String))) {
325                     throw new IllegalArgumentException("Name must be a String");
326                 }
327                 mEmptyName = false;
328                 mName = (String)headerValue;
329                 break;
330             case TYPE:
331                 if ((headerValue != null) && (!(headerValue instanceof String))) {
332                     throw new IllegalArgumentException("Type must be a String");
333                 }
334                 mType = (String)headerValue;
335                 break;
336             case LENGTH:
337                 if (!(headerValue instanceof Long)) {
338                     if (headerValue == null) {
339                         mLength = null;
340                         break;
341                     }
342                     throw new IllegalArgumentException("Length must be a Long");
343                 }
344                 temp = ((Long)headerValue).longValue();
345                 if ((temp < 0L) || (temp > 0xFFFFFFFFL)) {
346                     throw new IllegalArgumentException("Length must be between 0 and 0xFFFFFFFF");
347                 }
348                 mLength = (Long)headerValue;
349                 break;
350             case TIME_ISO_8601:
351                 if ((headerValue != null) && (!(headerValue instanceof Calendar))) {
352                     throw new IllegalArgumentException("Time ISO 8601 must be a Calendar");
353                 }
354                 mIsoTime = (Calendar)headerValue;
355                 break;
356             case TIME_4_BYTE:
357                 if ((headerValue != null) && (!(headerValue instanceof Calendar))) {
358                     throw new IllegalArgumentException("Time 4 Byte must be a Calendar");
359                 }
360                 mByteTime = (Calendar)headerValue;
361                 break;
362             case DESCRIPTION:
363                 if ((headerValue != null) && (!(headerValue instanceof String))) {
364                     throw new IllegalArgumentException("Description must be a String");
365                 }
366                 mDescription = (String)headerValue;
367                 break;
368             case TARGET:
369                 if (headerValue == null) {
370                     mTarget = null;
371                 } else {
372                     if (!(headerValue instanceof byte[])) {
373                         throw new IllegalArgumentException("Target must be a byte array");
374                     } else {
375                         mTarget = new byte[((byte[])headerValue).length];
376                         System.arraycopy(headerValue, 0, mTarget, 0, mTarget.length);
377                     }
378                 }
379                 break;
380             case HTTP:
381                 if (headerValue == null) {
382                     mHttpHeader = null;
383                 } else {
384                     if (!(headerValue instanceof byte[])) {
385                         throw new IllegalArgumentException("HTTP must be a byte array");
386                     } else {
387                         mHttpHeader = new byte[((byte[])headerValue).length];
388                         System.arraycopy(headerValue, 0, mHttpHeader, 0, mHttpHeader.length);
389                     }
390                 }
391                 break;
392             case WHO:
393                 if (headerValue == null) {
394                     mWho = null;
395                 } else {
396                     if (!(headerValue instanceof byte[])) {
397                         throw new IllegalArgumentException("WHO must be a byte array");
398                     } else {
399                         mWho = new byte[((byte[])headerValue).length];
400                         System.arraycopy(headerValue, 0, mWho, 0, mWho.length);
401                     }
402                 }
403                 break;
404             case OBJECT_CLASS:
405                 if (headerValue == null) {
406                     mObjectClass = null;
407                 } else {
408                     if (!(headerValue instanceof byte[])) {
409                         throw new IllegalArgumentException("Object Class must be a byte array");
410                     } else {
411                         mObjectClass = new byte[((byte[])headerValue).length];
412                         System.arraycopy(headerValue, 0, mObjectClass, 0, mObjectClass.length);
413                     }
414                 }
415                 break;
416             case APPLICATION_PARAMETER:
417                 if (headerValue == null) {
418                     mAppParam = null;
419                 } else {
420                     if (!(headerValue instanceof byte[])) {
421                         throw new IllegalArgumentException(
422                                 "Application Parameter must be a byte array");
423                     } else {
424                         mAppParam = new byte[((byte[])headerValue).length];
425                         System.arraycopy(headerValue, 0, mAppParam, 0, mAppParam.length);
426                     }
427                 }
428                 break;
429             case SINGLE_RESPONSE_MODE:
430                 if (headerValue == null) {
431                     mSingleResponseMode = null;
432                 } else {
433                     if (!(headerValue instanceof Byte)) {
434                         throw new IllegalArgumentException(
435                                 "Single Response Mode must be a Byte");
436                     } else {
437                         mSingleResponseMode = (Byte)headerValue;
438                     }
439                 }
440                 break;
441             case SINGLE_RESPONSE_MODE_PARAMETER:
442                 if (headerValue == null) {
443                     mSrmParam = null;
444                 } else {
445                     if (!(headerValue instanceof Byte)) {
446                         throw new IllegalArgumentException(
447                                 "Single Response Mode Parameter must be a Byte");
448                     } else {
449                         mSrmParam = (Byte)headerValue;
450                     }
451                 }
452                 break;
453             default:
454                 // Verify that it was not a Unicode String user Defined
455                 if ((headerID >= 0x30) && (headerID <= 0x3F)) {
456                     if ((headerValue != null) && (!(headerValue instanceof String))) {
457                         throw new IllegalArgumentException(
458                                 "Unicode String User Defined must be a String");
459                     }
460                     mUnicodeUserDefined[headerID - 0x30] = (String)headerValue;
461 
462                     break;
463                 }
464                 // Verify that it was not a byte sequence user defined value
465                 if ((headerID >= 0x70) && (headerID <= 0x7F)) {
466 
467                     if (headerValue == null) {
468                         mSequenceUserDefined[headerID - 0x70] = null;
469                     } else {
470                         if (!(headerValue instanceof byte[])) {
471                             throw new IllegalArgumentException(
472                                     "Byte Sequence User Defined must be a byte array");
473                         } else {
474                             mSequenceUserDefined[headerID - 0x70]
475                                     = new byte[((byte[])headerValue).length];
476                             System.arraycopy(headerValue, 0, mSequenceUserDefined[headerID - 0x70],
477                                     0, mSequenceUserDefined[headerID - 0x70].length);
478                         }
479                     }
480                     break;
481                 }
482                 // Verify that it was not a Byte user Defined
483                 if ((headerID >= 0xB0) && (headerID <= 0xBF)) {
484                     if ((headerValue != null) && (!(headerValue instanceof Byte))) {
485                         throw new IllegalArgumentException("ByteUser Defined must be a Byte");
486                     }
487                     mByteUserDefined[headerID - 0xB0] = (Byte)headerValue;
488 
489                     break;
490                 }
491                 // Verify that is was not the 4 byte unsigned integer user
492                 // defined header
493                 if ((headerID >= 0xF0) && (headerID <= 0xFF)) {
494                     if (!(headerValue instanceof Long)) {
495                         if (headerValue == null) {
496                             mIntegerUserDefined[headerID - 0xF0] = null;
497                             break;
498                         }
499                         throw new IllegalArgumentException("Integer User Defined must be a Long");
500                     }
501                     temp = ((Long)headerValue).longValue();
502                     if ((temp < 0L) || (temp > 0xFFFFFFFFL)) {
503                         throw new IllegalArgumentException(
504                                 "Integer User Defined must be between 0 and 0xFFFFFFFF");
505                     }
506                     mIntegerUserDefined[headerID - 0xF0] = (Long)headerValue;
507                     break;
508                 }
509                 throw new IllegalArgumentException("Invalid Header Identifier");
510         }
511     }
512 
513     /**
514      * Retrieves the value of the header identifier provided. The type of the
515      * Object returned is defined in the description of this interface.
516      * @param headerID the header identifier whose value is to be returned
517      * @return the value of the header provided or <code>null</code> if the
518      *         header identifier specified is not part of this
519      *         <code>HeaderSet</code> object
520      * @throws IllegalArgumentException if the <code>headerID</code> is not one
521      *         defined in this interface or any of the user-defined headers
522      * @throws IOException if an error occurred in the transport layer during
523      *         the operation or if the connection has been closed
524      */
getHeader(int headerID)525     public Object getHeader(int headerID) throws IOException {
526 
527         switch (headerID) {
528             case COUNT:
529                 return mCount;
530             case NAME:
531                 return mName;
532             case TYPE:
533                 return mType;
534             case LENGTH:
535                 return mLength;
536             case TIME_ISO_8601:
537                 return mIsoTime;
538             case TIME_4_BYTE:
539                 return mByteTime;
540             case DESCRIPTION:
541                 return mDescription;
542             case TARGET:
543                 return mTarget;
544             case HTTP:
545                 return mHttpHeader;
546             case WHO:
547                 return mWho;
548             case CONNECTION_ID:
549                 return mConnectionID;
550             case OBJECT_CLASS:
551                 return mObjectClass;
552             case APPLICATION_PARAMETER:
553                 return mAppParam;
554             case SINGLE_RESPONSE_MODE:
555                 return mSingleResponseMode;
556             case SINGLE_RESPONSE_MODE_PARAMETER:
557                 return mSrmParam;
558             default:
559                 // Verify that it was not a Unicode String user Defined
560                 if ((headerID >= 0x30) && (headerID <= 0x3F)) {
561                     return mUnicodeUserDefined[headerID - 0x30];
562                 }
563                 // Verify that it was not a byte sequence user defined header
564                 if ((headerID >= 0x70) && (headerID <= 0x7F)) {
565                     return mSequenceUserDefined[headerID - 0x70];
566                 }
567                 // Verify that it was not a byte user defined header
568                 if ((headerID >= 0xB0) && (headerID <= 0xBF)) {
569                     return mByteUserDefined[headerID - 0xB0];
570                 }
571                 // Verify that it was not a integer user defined header
572                 if ((headerID >= 0xF0) && (headerID <= 0xFF)) {
573                     return mIntegerUserDefined[headerID - 0xF0];
574                 }
575                 throw new IllegalArgumentException("Invalid Header Identifier");
576         }
577     }
578 
579     /**
580      * Retrieves the list of headers that may be retrieved via the
581      * <code>getHeader</code> method that will not return <code>null</code>. In
582      * other words, this method returns all the headers that are available in
583      * this object.
584      * @see #getHeader
585      * @return the array of headers that are set in this object or
586      *         <code>null</code> if no headers are available
587      * @throws IOException if an error occurred in the transport layer during
588      *         the operation or the connection has been closed
589      *
590      * @hide
591      */
getHeaderList()592     public int[] getHeaderList() throws IOException {
593         ByteArrayOutputStream out = new ByteArrayOutputStream();
594 
595         if (mCount != null) {
596             out.write(COUNT);
597         }
598         if (mName != null) {
599             out.write(NAME);
600         }
601         if (mType != null) {
602             out.write(TYPE);
603         }
604         if (mLength != null) {
605             out.write(LENGTH);
606         }
607         if (mIsoTime != null) {
608             out.write(TIME_ISO_8601);
609         }
610         if (mByteTime != null) {
611             out.write(TIME_4_BYTE);
612         }
613         if (mDescription != null) {
614             out.write(DESCRIPTION);
615         }
616         if (mTarget != null) {
617             out.write(TARGET);
618         }
619         if (mHttpHeader != null) {
620             out.write(HTTP);
621         }
622         if (mWho != null) {
623             out.write(WHO);
624         }
625         if (mAppParam != null) {
626             out.write(APPLICATION_PARAMETER);
627         }
628         if (mObjectClass != null) {
629             out.write(OBJECT_CLASS);
630         }
631         if(mSingleResponseMode != null) {
632             out.write(SINGLE_RESPONSE_MODE);
633         }
634         if(mSrmParam != null) {
635             out.write(SINGLE_RESPONSE_MODE_PARAMETER);
636         }
637 
638         for (int i = 0x30; i < 0x40; i++) {
639             if (mUnicodeUserDefined[i - 0x30] != null) {
640                 out.write(i);
641             }
642         }
643 
644         for (int i = 0x70; i < 0x80; i++) {
645             if (mSequenceUserDefined[i - 0x70] != null) {
646                 out.write(i);
647             }
648         }
649 
650         for (int i = 0xB0; i < 0xC0; i++) {
651             if (mByteUserDefined[i - 0xB0] != null) {
652                 out.write(i);
653             }
654         }
655 
656         for (int i = 0xF0; i < 0x100; i++) {
657             if (mIntegerUserDefined[i - 0xF0] != null) {
658                 out.write(i);
659             }
660         }
661 
662         byte[] headers = out.toByteArray();
663         out.close();
664 
665         if ((headers == null) || (headers.length == 0)) {
666             return null;
667         }
668 
669         int[] result = new int[headers.length];
670         for (int i = 0; i < headers.length; i++) {
671             // Convert the byte to a positive integer.  That is, an integer
672             // between 0 and 256.
673             result[i] = headers[i] & 0xFF;
674         }
675 
676         return result;
677     }
678 
679     /**
680      * Sets the authentication challenge header. The <code>realm</code> will be
681      * encoded based upon the default encoding scheme used by the implementation
682      * to encode strings. Therefore, the encoding scheme used to encode the
683      * <code>realm</code> is application dependent.
684      * @param realm a short description that describes what password to use; if
685      *        <code>null</code> no realm will be sent in the authentication
686      *        challenge header
687      * @param userID if <code>true</code>, a user ID is required in the reply;
688      *        if <code>false</code>, no user ID is required
689      * @param access if <code>true</code> then full access will be granted if
690      *        successful; if <code>false</code> then read-only access will be
691      *        granted if successful
692      * @throws IOException
693      *
694      * @hide
695      */
createAuthenticationChallenge(String realm, boolean userID, boolean access)696     public void createAuthenticationChallenge(String realm, boolean userID, boolean access)
697             throws IOException {
698 
699         nonce = new byte[16];
700         if(mRandom == null) {
701             mRandom = new SecureRandom();
702         }
703         for (int i = 0; i < 16; i++) {
704             nonce[i] = (byte)mRandom.nextInt();
705         }
706 
707         mAuthChall = ObexHelper.computeAuthenticationChallenge(nonce, realm, access, userID);
708     }
709 
710     /**
711      * Returns the response code received from the server. Response codes are
712      * defined in the <code>ResponseCodes</code> class.
713      * @see ResponseCodes
714      * @return the response code retrieved from the server
715      * @throws IOException if an error occurred in the transport layer during
716      *         the transaction; if this method is called on a
717      *         <code>HeaderSet</code> object created by calling
718      *         <code>createHeaderSet()</code> in a <code>ClientSession</code>
719      *         object; if this object was created by an OBEX server
720      */
getResponseCode()721     public int getResponseCode() throws IOException {
722         if (responseCode == -1) {
723             throw new IOException("May not be called on a server");
724         } else {
725             return responseCode;
726         }
727     }
728 }
729