Obex library cleanup, third pass
- Change variable namings - Remove interface public modifier - Move 2 duplicate methods to ObexSession - Removed unused code and variables - Use static variables for some protocol defines
This commit is contained in:
@@ -37,9 +37,11 @@ package javax.obex;
|
||||
*/
|
||||
public final class ApplicationParameter {
|
||||
|
||||
private byte[] b_array;
|
||||
private int length;
|
||||
private int max_length = 1000;
|
||||
private byte[] mArray;
|
||||
|
||||
private int mLength;
|
||||
|
||||
private int mMaxLength = 1000;
|
||||
|
||||
public static class TRIPLET_TAGID {
|
||||
public static final byte ORDER_TAGID = 0x01;
|
||||
@@ -91,7 +93,6 @@ public final class ApplicationParameter {
|
||||
public static class TRIPLET_LENGTH {
|
||||
public static final byte ORDER_LENGTH = 1;
|
||||
|
||||
//public final byte SEARCH_VALUE_LENGTH = 0x02;
|
||||
public static final byte SEARCH_ATTRIBUTE_LENGTH = 1;
|
||||
|
||||
public static final byte MAXLISTCOUNT_LENGTH = 2;
|
||||
@@ -107,34 +108,27 @@ public final class ApplicationParameter {
|
||||
public static final byte NEWMISSEDCALLS_LENGTH = 1;
|
||||
}
|
||||
|
||||
/*
|
||||
public class TRIPLET_STRUCTURE{
|
||||
TRIPLET_TAGID id;
|
||||
TRIPLET_LENGTH length;
|
||||
byte[] value;
|
||||
}
|
||||
*/
|
||||
public ApplicationParameter() {
|
||||
b_array = new byte[max_length];
|
||||
length = 0;
|
||||
mArray = new byte[mMaxLength];
|
||||
mLength = 0;
|
||||
}
|
||||
|
||||
public void addAPPHeader(byte tag, byte len, byte[] value) {
|
||||
if ((length + len + 2) > max_length) {
|
||||
byte[] array_tmp = new byte[length + 4 * len];
|
||||
System.arraycopy(b_array, 0, array_tmp, 0, length);
|
||||
b_array = array_tmp;
|
||||
max_length = length + 4 * len;
|
||||
if ((mLength + len + 2) > mMaxLength) {
|
||||
byte[] array_tmp = new byte[mLength + 4 * len];
|
||||
System.arraycopy(mArray, 0, array_tmp, 0, mLength);
|
||||
mArray = array_tmp;
|
||||
mMaxLength = mLength + 4 * len;
|
||||
}
|
||||
b_array[length++] = tag;
|
||||
b_array[length++] = len;
|
||||
System.arraycopy(value, 0, b_array, length, len);
|
||||
length += len;
|
||||
mArray[mLength++] = tag;
|
||||
mArray[mLength++] = len;
|
||||
System.arraycopy(value, 0, mArray, mLength, len);
|
||||
mLength += len;
|
||||
}
|
||||
|
||||
public byte[] getAPPparam() {
|
||||
byte[] para = new byte[length];
|
||||
System.arraycopy(b_array, 0, para, 0, length);
|
||||
byte[] para = new byte[mLength];
|
||||
System.arraycopy(mArray, 0, para, 0, mLength);
|
||||
return para;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -106,8 +106,8 @@ public interface Authenticator {
|
||||
* @return a <code>PasswordAuthentication</code> object containing the
|
||||
* user name and password used for authentication
|
||||
*/
|
||||
public PasswordAuthentication onAuthenticationChallenge(String description,
|
||||
boolean isUserIdRequired, boolean isFullAccess);
|
||||
PasswordAuthentication onAuthenticationChallenge(String description, boolean isUserIdRequired,
|
||||
boolean isFullAccess);
|
||||
|
||||
/**
|
||||
* Called when a client or server receives an authentication response
|
||||
@@ -120,5 +120,5 @@ public interface Authenticator {
|
||||
* @return the correct password for the user name provided; if
|
||||
* <code>null</code> is returned then the authentication request failed
|
||||
*/
|
||||
public byte[] onAuthenticationResponse(byte[] userName);
|
||||
byte[] onAuthenticationResponse(byte[] userName);
|
||||
}
|
||||
|
||||
@@ -47,7 +47,7 @@ public interface BaseStream {
|
||||
*
|
||||
* @throws IOException if the object is closed
|
||||
*/
|
||||
public void ensureOpen() throws IOException;
|
||||
void ensureOpen() throws IOException;
|
||||
|
||||
/**
|
||||
* Verifies that additional information may be sent. In other words, the
|
||||
@@ -55,7 +55,7 @@ public interface BaseStream {
|
||||
*
|
||||
* @throws IOException if the operation is completed
|
||||
*/
|
||||
public void ensureNotDone() throws IOException;
|
||||
void ensureNotDone() throws IOException;
|
||||
|
||||
/**
|
||||
* Continues the operation since there is no data to read.
|
||||
@@ -69,7 +69,7 @@ public interface BaseStream {
|
||||
*
|
||||
* @throws IOException if an IO error occurs
|
||||
*/
|
||||
public boolean continueOperation(boolean sendEmpty, boolean inStream) throws IOException;
|
||||
boolean continueOperation(boolean sendEmpty, boolean inStream) throws IOException;
|
||||
|
||||
/**
|
||||
* Called when the output or input stream is closed.
|
||||
@@ -79,5 +79,5 @@ public interface BaseStream {
|
||||
*
|
||||
* @throws IOException if an IO error occurs
|
||||
*/
|
||||
public void streamClosed(boolean inStream) throws IOException;
|
||||
void streamClosed(boolean inStream) throws IOException;
|
||||
}
|
||||
|
||||
@@ -47,104 +47,82 @@ import java.io.ByteArrayOutputStream;
|
||||
*/
|
||||
public final class ClientOperation implements Operation, BaseStream {
|
||||
|
||||
/**
|
||||
* Defines the basic packet length used by OBEX. Event OBEX packet has the
|
||||
* same basic format:<BR>
|
||||
* Byte 0: Request or Response Code
|
||||
* Byte 1&2: Length of the packet.
|
||||
*/
|
||||
private static final int BASE_PACKET_LENGTH = 3;
|
||||
private ClientSession mParent;
|
||||
|
||||
private ClientSession parent;
|
||||
private boolean mInputOpen;
|
||||
|
||||
private InputStream socketInput;
|
||||
private PrivateInputStream mPrivateInput;
|
||||
|
||||
private PrivateInputStream privateInput;
|
||||
private boolean mPrivateInputOpen;
|
||||
|
||||
private PrivateOutputStream privateOutput;
|
||||
private PrivateOutputStream mPrivateOutput;
|
||||
|
||||
private boolean isClosed;
|
||||
private boolean mPrivateOutputOpen;
|
||||
|
||||
private String exceptionMessage;
|
||||
private String mExceptionMessage;
|
||||
|
||||
private int maxPacketSize;
|
||||
private int mMaxPacketSize;
|
||||
|
||||
private boolean isDone;
|
||||
private boolean mOperationDone;
|
||||
|
||||
private boolean isGet;
|
||||
private boolean mGetOperation;
|
||||
|
||||
private HeaderSet requestHeaders;
|
||||
private HeaderSet mRequestHeader;
|
||||
|
||||
private HeaderSet replyHeaders;
|
||||
private HeaderSet mReplyHeader;
|
||||
|
||||
private boolean isEndOfBodySent;
|
||||
|
||||
private boolean inputStreamOpened;
|
||||
|
||||
private boolean outputStreamOpened;
|
||||
|
||||
private boolean isValidateConnected;
|
||||
private boolean mEndOfBodySent;
|
||||
|
||||
/**
|
||||
* Creates new OperationImpl to read and write data to a server
|
||||
*
|
||||
* @param in the input stream to read from
|
||||
*
|
||||
* @param maxSize the maximum packet size
|
||||
*
|
||||
* @param p the parent to this object
|
||||
*
|
||||
* @param headers the headers to set in the initial request
|
||||
*
|
||||
* @param type <code>true</code> if this is a get request;
|
||||
* <code>false</code. if this is a put request
|
||||
* @param headers the headers to set in the initial request
|
||||
*
|
||||
* @throws IOExcpetion if the an IO error occured
|
||||
*/
|
||||
public ClientOperation(InputStream in, int maxSize, ClientSession p, HeaderSet header,
|
||||
boolean type) throws IOException {
|
||||
public ClientOperation(int maxSize, ClientSession p, HeaderSet header, boolean type)
|
||||
throws IOException {
|
||||
|
||||
parent = p;
|
||||
isEndOfBodySent = false;
|
||||
socketInput = in;
|
||||
isClosed = false;
|
||||
isDone = false;
|
||||
maxPacketSize = maxSize;
|
||||
isGet = type;
|
||||
mParent = p;
|
||||
mEndOfBodySent = false;
|
||||
mInputOpen = true;
|
||||
mOperationDone = false;
|
||||
mMaxPacketSize = maxSize;
|
||||
mGetOperation = type;
|
||||
|
||||
inputStreamOpened = false;
|
||||
outputStreamOpened = false;
|
||||
isValidateConnected = false;
|
||||
mPrivateInputOpen = false;
|
||||
mPrivateOutputOpen = false;
|
||||
mPrivateInput = null;
|
||||
mPrivateOutput = null;
|
||||
|
||||
privateInput = null;
|
||||
privateOutput = null;
|
||||
mReplyHeader = new HeaderSet();
|
||||
|
||||
replyHeaders = new HeaderSet();
|
||||
|
||||
requestHeaders = new HeaderSet();
|
||||
mRequestHeader = new HeaderSet();
|
||||
|
||||
int[] headerList = header.getHeaderList();
|
||||
|
||||
if (headerList != null) {
|
||||
|
||||
for (int i = 0; i < headerList.length; i++) {
|
||||
requestHeaders.setHeader(headerList[i], header.getHeader(headerList[i]));
|
||||
mRequestHeader.setHeader(headerList[i], header.getHeader(headerList[i]));
|
||||
}
|
||||
}
|
||||
|
||||
if ((header).authChall != null) {
|
||||
requestHeaders.authChall = new byte[(header).authChall.length];
|
||||
System.arraycopy((header).authChall, 0, requestHeaders.authChall, 0,
|
||||
(header).authChall.length);
|
||||
if ((header).mAuthChall != null) {
|
||||
mRequestHeader.mAuthChall = new byte[(header).mAuthChall.length];
|
||||
System.arraycopy((header).mAuthChall, 0, mRequestHeader.mAuthChall, 0,
|
||||
(header).mAuthChall.length);
|
||||
}
|
||||
|
||||
if ((header).authResp != null) {
|
||||
requestHeaders.authResp = new byte[(header).authResp.length];
|
||||
System.arraycopy((header).authResp, 0, requestHeaders.authResp, 0,
|
||||
(header).authResp.length);
|
||||
if ((header).mAuthResp != null) {
|
||||
mRequestHeader.mAuthResp = new byte[(header).mAuthResp.length];
|
||||
System.arraycopy((header).mAuthResp, 0, mRequestHeader.mAuthResp, 0,
|
||||
(header).mAuthResp.length);
|
||||
|
||||
}
|
||||
// requestHeaders = (HeaderSet)header;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -163,24 +141,24 @@ public final class ClientOperation implements Operation, BaseStream {
|
||||
// }
|
||||
|
||||
//no compatible with sun-ri
|
||||
if ((isDone) && (replyHeaders.responseCode != ObexHelper.OBEX_HTTP_CONTINUE)) {
|
||||
if ((mOperationDone) && (mReplyHeader.responseCode != ResponseCodes.OBEX_HTTP_CONTINUE)) {
|
||||
throw new IOException("Operation has already ended");
|
||||
}
|
||||
|
||||
exceptionMessage = "Operation aborted";
|
||||
if ((!isDone) && (replyHeaders.responseCode == ObexHelper.OBEX_HTTP_CONTINUE)) {
|
||||
isDone = true;
|
||||
mExceptionMessage = "Operation aborted";
|
||||
if ((!mOperationDone) && (mReplyHeader.responseCode == ResponseCodes.OBEX_HTTP_CONTINUE)) {
|
||||
mOperationDone = true;
|
||||
/*
|
||||
* Since we are not sending any headers or returning any headers then
|
||||
* we just need to write and read the same bytes
|
||||
*/
|
||||
parent.sendRequest(0xFF, null, replyHeaders, null);
|
||||
mParent.sendRequest(ObexHelper.OBEX_OPCODE_ABORT, null, mReplyHeader, null);
|
||||
|
||||
if (replyHeaders.responseCode != ResponseCodes.OBEX_HTTP_OK) {
|
||||
if (mReplyHeader.responseCode != ResponseCodes.OBEX_HTTP_OK) {
|
||||
throw new IOException("Invalid response code from server");
|
||||
}
|
||||
|
||||
exceptionMessage = null;
|
||||
mExceptionMessage = null;
|
||||
}
|
||||
|
||||
close();
|
||||
@@ -199,12 +177,12 @@ public final class ClientOperation implements Operation, BaseStream {
|
||||
*/
|
||||
public synchronized int getResponseCode() throws IOException {
|
||||
//avoid dup validateConnection
|
||||
if ((replyHeaders.responseCode == -1)
|
||||
|| (replyHeaders.responseCode == ObexHelper.OBEX_HTTP_CONTINUE)) {
|
||||
if ((mReplyHeader.responseCode == -1)
|
||||
|| (mReplyHeader.responseCode == ResponseCodes.OBEX_HTTP_CONTINUE)) {
|
||||
validateConnection();
|
||||
}
|
||||
|
||||
return replyHeaders.responseCode;
|
||||
return mReplyHeader.responseCode;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -226,7 +204,7 @@ public final class ClientOperation implements Operation, BaseStream {
|
||||
*/
|
||||
public String getType() {
|
||||
try {
|
||||
return (String)replyHeaders.getHeader(HeaderSet.TYPE);
|
||||
return (String)mReplyHeader.getHeader(HeaderSet.TYPE);
|
||||
} catch (IOException e) {
|
||||
return null;
|
||||
}
|
||||
@@ -242,7 +220,7 @@ public final class ClientOperation implements Operation, BaseStream {
|
||||
*/
|
||||
public long getLength() {
|
||||
try {
|
||||
Long temp = (Long)replyHeaders.getHeader(HeaderSet.LENGTH);
|
||||
Long temp = (Long)mReplyHeader.getHeader(HeaderSet.LENGTH);
|
||||
|
||||
if (temp == null) {
|
||||
return -1;
|
||||
@@ -262,27 +240,23 @@ public final class ClientOperation implements Operation, BaseStream {
|
||||
* @throws IOException if an I/O error occurs
|
||||
*/
|
||||
public InputStream openInputStream() throws IOException {
|
||||
// TODO: this mode is not set yet.
|
||||
// if ((parent.mode & Connector.READ) == 0)
|
||||
// throw new IOException("write-only connection");
|
||||
|
||||
ensureOpen();
|
||||
|
||||
if (inputStreamOpened)
|
||||
if (mPrivateInputOpen)
|
||||
throw new IOException("no more input streams available");
|
||||
if (isGet) {
|
||||
if (mGetOperation) {
|
||||
// send the GET request here
|
||||
validateConnection();
|
||||
isValidateConnected = true;
|
||||
} else {
|
||||
if (privateInput == null) {
|
||||
privateInput = new PrivateInputStream(this);
|
||||
if (mPrivateInput == null) {
|
||||
mPrivateInput = new PrivateInputStream(this);
|
||||
}
|
||||
}
|
||||
|
||||
inputStreamOpened = true;
|
||||
mPrivateInputOpen = true;
|
||||
|
||||
return privateInput;
|
||||
return mPrivateInput;
|
||||
}
|
||||
|
||||
/**8
|
||||
@@ -304,27 +278,25 @@ public final class ClientOperation implements Operation, BaseStream {
|
||||
* @throws IOException if an I/O error occurs
|
||||
*/
|
||||
public OutputStream openOutputStream() throws IOException {
|
||||
// TODO: this mode is not set yet.
|
||||
// if ((parent.mode & Connector.WRITE) == 0)
|
||||
// throw new IOException("read-only connection");
|
||||
|
||||
ensureOpen();
|
||||
ensureNotDone();
|
||||
|
||||
if (outputStreamOpened)
|
||||
if (mPrivateOutputOpen)
|
||||
throw new IOException("no more output streams available");
|
||||
|
||||
if (privateOutput == null) {
|
||||
if (mPrivateOutput == null) {
|
||||
// there are 3 bytes operation headers and 3 bytes body headers //
|
||||
privateOutput = new PrivateOutputStream(this, maxPacketSize - 6);
|
||||
mPrivateOutput = new PrivateOutputStream(this, mMaxPacketSize - 6);
|
||||
}
|
||||
|
||||
outputStreamOpened = true;
|
||||
mPrivateOutputOpen = true;
|
||||
|
||||
return privateOutput;
|
||||
return mPrivateOutput;
|
||||
}
|
||||
|
||||
public int getMaxPacketSize() {
|
||||
return maxPacketSize - 6;
|
||||
return mMaxPacketSize - 6;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -344,10 +316,10 @@ public final class ClientOperation implements Operation, BaseStream {
|
||||
* @throws IOException if the operation has already ended or is closed
|
||||
*/
|
||||
public void close() throws IOException {
|
||||
isClosed = true;
|
||||
inputStreamOpened = false;
|
||||
outputStreamOpened = false;
|
||||
parent.setRequestInactive();
|
||||
mInputOpen = false;
|
||||
mPrivateInputOpen = false;
|
||||
mPrivateOutputOpen = false;
|
||||
mParent.setRequestInactive();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -359,10 +331,10 @@ public final class ClientOperation implements Operation, BaseStream {
|
||||
*
|
||||
* @throws IOException if this <code>Operation</code> has been closed
|
||||
*/
|
||||
public HeaderSet getReceivedHeaders() throws IOException {
|
||||
public HeaderSet getReceivedHeader() throws IOException {
|
||||
ensureOpen();
|
||||
|
||||
return replyHeaders;
|
||||
return mReplyHeader;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -381,18 +353,18 @@ public final class ClientOperation implements Operation, BaseStream {
|
||||
*/
|
||||
public void sendHeaders(HeaderSet headers) throws IOException {
|
||||
ensureOpen();
|
||||
if (isDone) {
|
||||
if (mOperationDone) {
|
||||
throw new IOException("Operation has already exchanged all data");
|
||||
}
|
||||
|
||||
if (headers == null) {
|
||||
throw new NullPointerException("Headers may not be null");
|
||||
throw new IOException("Headers may not be null");
|
||||
}
|
||||
|
||||
int[] headerList = headers.getHeaderList();
|
||||
if (headerList != null) {
|
||||
for (int i = 0; i < headerList.length; i++) {
|
||||
requestHeaders.setHeader(headerList[i], headers.getHeader(headerList[i]));
|
||||
mRequestHeader.setHeader(headerList[i], headers.getHeader(headerList[i]));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -406,49 +378,50 @@ public final class ClientOperation implements Operation, BaseStream {
|
||||
*
|
||||
* @throws IOException if an IO error occurred
|
||||
*/
|
||||
/*
|
||||
private boolean readResponse() throws IOException {
|
||||
replyHeaders.responseCode = socketInput.read();
|
||||
int packetLength = socketInput.read();
|
||||
packetLength = (packetLength << 8) + socketInput.read();
|
||||
mReplyHeader.responseCode = mInput.read();
|
||||
int packetLength = mInput.read();
|
||||
packetLength = (packetLength << 8) + mInput.read();
|
||||
|
||||
if (packetLength > ObexHelper.MAX_PACKET_SIZE_INT) {
|
||||
if (exceptionMessage != null) {
|
||||
if (mExceptionMessage != null) {
|
||||
abort();
|
||||
}
|
||||
throw new IOException("Received a packet that was too big");
|
||||
}
|
||||
|
||||
if (packetLength > BASE_PACKET_LENGTH) {
|
||||
int dataLength = packetLength - BASE_PACKET_LENGTH;
|
||||
if (packetLength > ObexHelper.BASE_PACKET_LENGTH) {
|
||||
int dataLength = packetLength - ObexHelper.BASE_PACKET_LENGTH;
|
||||
byte[] data = new byte[dataLength];
|
||||
int readLength = socketInput.read(data);
|
||||
int readLength = mInput.read(data);
|
||||
if (readLength != dataLength) {
|
||||
throw new IOException("Received a packet without data as decalred length");
|
||||
}
|
||||
byte[] body = ObexHelper.updateHeaderSet(replyHeaders, data);
|
||||
byte[] body = ObexHelper.updateHeaderSet(mReplyHeader, data);
|
||||
|
||||
if (body != null) {
|
||||
privateInput.writeBytes(body, 1);
|
||||
mPrivateInput.writeBytes(body, 1);
|
||||
|
||||
/*
|
||||
* Determine if a body (0x48) header or an end of body (0x49)
|
||||
* was received. If we received an end of body and
|
||||
* a response code of OBEX_HTTP_OK, then the operation should
|
||||
* end.
|
||||
*/
|
||||
if ((body[0] == 0x49) && (replyHeaders.responseCode == ResponseCodes.OBEX_HTTP_OK)) {
|
||||
*
|
||||
if ((body[0] == 0x49) && (mReplyHeader.responseCode == ResponseCodes.OBEX_HTTP_OK)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (replyHeaders.responseCode == ObexHelper.OBEX_HTTP_CONTINUE) {
|
||||
if (mReplyHeader.responseCode == ResponseCodes.OBEX_HTTP_CONTINUE) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
*/
|
||||
/**
|
||||
* Verifies that additional information may be sent. In other words, the
|
||||
* operation is not done.
|
||||
@@ -456,7 +429,7 @@ public final class ClientOperation implements Operation, BaseStream {
|
||||
* @throws IOException if the operation is completed
|
||||
*/
|
||||
public void ensureNotDone() throws IOException {
|
||||
if (isDone) {
|
||||
if (mOperationDone) {
|
||||
throw new IOException("Operation has completed");
|
||||
}
|
||||
}
|
||||
@@ -467,12 +440,12 @@ public final class ClientOperation implements Operation, BaseStream {
|
||||
* @throws IOException if an exception needs to be thrown
|
||||
*/
|
||||
public void ensureOpen() throws IOException {
|
||||
parent.ensureOpen();
|
||||
mParent.ensureOpen();
|
||||
|
||||
if (exceptionMessage != null) {
|
||||
throw new IOException(exceptionMessage);
|
||||
if (mExceptionMessage != null) {
|
||||
throw new IOException(mExceptionMessage);
|
||||
}
|
||||
if (isClosed) {
|
||||
if (!mInputOpen) {
|
||||
throw new IOException("Operation has already ended");
|
||||
}
|
||||
}
|
||||
@@ -486,7 +459,7 @@ public final class ClientOperation implements Operation, BaseStream {
|
||||
ensureOpen();
|
||||
|
||||
// to sure only one privateInput object exist.
|
||||
if (privateInput == null) {
|
||||
if (mPrivateInput == null) {
|
||||
startProcessing();
|
||||
}
|
||||
}
|
||||
@@ -501,13 +474,13 @@ public final class ClientOperation implements Operation, BaseStream {
|
||||
*
|
||||
* @throws IOException if an IO error occurs
|
||||
*/
|
||||
protected boolean sendRequest(int type) throws IOException {
|
||||
private boolean sendRequest(int type) throws IOException {
|
||||
boolean returnValue = false;
|
||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||
int bodyLength = -1;
|
||||
byte[] headerArray = ObexHelper.createHeader(requestHeaders, true);
|
||||
if (privateOutput != null) {
|
||||
bodyLength = privateOutput.size();
|
||||
byte[] headerArray = ObexHelper.createHeader(mRequestHeader, true);
|
||||
if (mPrivateOutput != null) {
|
||||
bodyLength = mPrivateOutput.size();
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -518,40 +491,39 @@ public final class ClientOperation implements Operation, BaseStream {
|
||||
* length, but it is a waste of resources if we can't send much of
|
||||
* the body.
|
||||
*/
|
||||
if ((BASE_PACKET_LENGTH + headerArray.length) > maxPacketSize) {
|
||||
if ((ObexHelper.BASE_PACKET_LENGTH + headerArray.length) > mMaxPacketSize) {
|
||||
int end = 0;
|
||||
int start = 0;
|
||||
// split & send the headerArray in multiple packets.
|
||||
|
||||
while (end != headerArray.length) {
|
||||
//split the headerArray
|
||||
end = ObexHelper.findHeaderEnd(headerArray, start, maxPacketSize
|
||||
- BASE_PACKET_LENGTH);
|
||||
end = ObexHelper.findHeaderEnd(headerArray, start, mMaxPacketSize
|
||||
- ObexHelper.BASE_PACKET_LENGTH);
|
||||
// can not split
|
||||
if (end == -1) {
|
||||
isDone = true;
|
||||
mOperationDone = true;
|
||||
abort();
|
||||
// isDone = true;
|
||||
exceptionMessage = "Header larger then can be sent in a packet";
|
||||
isClosed = true;
|
||||
mExceptionMessage = "Header larger then can be sent in a packet";
|
||||
mInputOpen = false;
|
||||
|
||||
if (privateInput != null) {
|
||||
privateInput.close();
|
||||
if (mPrivateInput != null) {
|
||||
mPrivateInput.close();
|
||||
}
|
||||
|
||||
if (privateOutput != null) {
|
||||
privateOutput.close();
|
||||
if (mPrivateOutput != null) {
|
||||
mPrivateOutput.close();
|
||||
}
|
||||
throw new IOException("OBEX Packet exceeds max packet size");
|
||||
}
|
||||
|
||||
byte[] sendHeader = new byte[end - start];
|
||||
System.arraycopy(headerArray, start, sendHeader, 0, sendHeader.length);
|
||||
if (!parent.sendRequest(type, sendHeader, replyHeaders, privateInput)) {
|
||||
if (!mParent.sendRequest(type, sendHeader, mReplyHeader, mPrivateInput)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (replyHeaders.responseCode != ObexHelper.OBEX_HTTP_CONTINUE) {
|
||||
if (mReplyHeader.responseCode != ResponseCodes.OBEX_HTTP_CONTINUE) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -569,27 +541,27 @@ public final class ClientOperation implements Operation, BaseStream {
|
||||
|
||||
if (bodyLength > 0) {
|
||||
/*
|
||||
* Determine if I can send the whole body or just part of
|
||||
* Determine if we can send the whole body or just part of
|
||||
* the body. Remember that there is the 3 bytes for the
|
||||
* response message and 3 bytes for the header ID and length
|
||||
*/
|
||||
if (bodyLength > (maxPacketSize - headerArray.length - 6)) {
|
||||
if (bodyLength > (mMaxPacketSize - headerArray.length - 6)) {
|
||||
returnValue = true;
|
||||
|
||||
bodyLength = maxPacketSize - headerArray.length - 6;
|
||||
bodyLength = mMaxPacketSize - headerArray.length - 6;
|
||||
}
|
||||
|
||||
byte[] body = privateOutput.readBytes(bodyLength);
|
||||
byte[] body = mPrivateOutput.readBytes(bodyLength);
|
||||
|
||||
/*
|
||||
* Since this is a put request if the final bit is set or
|
||||
* the output stream is closed we need to send the 0x49
|
||||
* (End of Body) otherwise, we need to send 0x48 (Body)
|
||||
*/
|
||||
if ((privateOutput.isClosed()) && (!returnValue) && (!isEndOfBodySent)
|
||||
if ((mPrivateOutput.isClosed()) && (!returnValue) && (!mEndOfBodySent)
|
||||
&& ((type & 0x80) != 0)) {
|
||||
out.write(0x49);
|
||||
isEndOfBodySent = true;
|
||||
mEndOfBodySent = true;
|
||||
} else {
|
||||
out.write(0x48);
|
||||
}
|
||||
@@ -603,13 +575,13 @@ public final class ClientOperation implements Operation, BaseStream {
|
||||
}
|
||||
}
|
||||
|
||||
if (outputStreamOpened && bodyLength <= 0 && !isEndOfBodySent) {
|
||||
if (mPrivateOutputOpen && bodyLength <= 0 && !mEndOfBodySent) {
|
||||
// only 0x82 or 0x83 can send 0x49
|
||||
if ((type & 0x80) == 0) {
|
||||
out.write(0x48);
|
||||
} else {
|
||||
out.write(0x49);
|
||||
isEndOfBodySent = true;
|
||||
mEndOfBodySent = true;
|
||||
|
||||
}
|
||||
|
||||
@@ -619,19 +591,19 @@ public final class ClientOperation implements Operation, BaseStream {
|
||||
}
|
||||
|
||||
if (out.size() == 0) {
|
||||
if (!parent.sendRequest(type, null, replyHeaders, privateInput)) {
|
||||
if (!mParent.sendRequest(type, null, mReplyHeader, mPrivateInput)) {
|
||||
return false;
|
||||
}
|
||||
return returnValue;
|
||||
}
|
||||
if ((out.size() > 0)
|
||||
&& (!parent.sendRequest(type, out.toByteArray(), replyHeaders, privateInput))) {
|
||||
&& (!mParent.sendRequest(type, out.toByteArray(), mReplyHeader, mPrivateInput))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// send all of the output data in 0x48,
|
||||
// send 0x49 with empty body
|
||||
if ((privateOutput != null) && (privateOutput.size() > 0))
|
||||
if ((mPrivateOutput != null) && (mPrivateOutput.size() > 0))
|
||||
returnValue = true;
|
||||
|
||||
return returnValue;
|
||||
@@ -646,41 +618,41 @@ public final class ClientOperation implements Operation, BaseStream {
|
||||
*/
|
||||
private synchronized void startProcessing() throws IOException {
|
||||
|
||||
if (privateInput == null) {
|
||||
privateInput = new PrivateInputStream(this);
|
||||
if (mPrivateInput == null) {
|
||||
mPrivateInput = new PrivateInputStream(this);
|
||||
}
|
||||
boolean more = true;
|
||||
|
||||
if (isGet) {
|
||||
if (!isDone) {
|
||||
replyHeaders.responseCode = ObexHelper.OBEX_HTTP_CONTINUE;
|
||||
while ((more) && (replyHeaders.responseCode == ObexHelper.OBEX_HTTP_CONTINUE)) {
|
||||
if (mGetOperation) {
|
||||
if (!mOperationDone) {
|
||||
mReplyHeader.responseCode = ResponseCodes.OBEX_HTTP_CONTINUE;
|
||||
while ((more) && (mReplyHeader.responseCode == ResponseCodes.OBEX_HTTP_CONTINUE)) {
|
||||
more = sendRequest(0x03);
|
||||
}
|
||||
|
||||
if (replyHeaders.responseCode == ObexHelper.OBEX_HTTP_CONTINUE) {
|
||||
parent.sendRequest(0x83, null, replyHeaders, privateInput);
|
||||
if (mReplyHeader.responseCode == ResponseCodes.OBEX_HTTP_CONTINUE) {
|
||||
mParent.sendRequest(0x83, null, mReplyHeader, mPrivateInput);
|
||||
}
|
||||
if (replyHeaders.responseCode != ObexHelper.OBEX_HTTP_CONTINUE) {
|
||||
isDone = true;
|
||||
if (mReplyHeader.responseCode != ResponseCodes.OBEX_HTTP_CONTINUE) {
|
||||
mOperationDone = true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
||||
if (!isDone) {
|
||||
replyHeaders.responseCode = ObexHelper.OBEX_HTTP_CONTINUE;
|
||||
while ((more) && (replyHeaders.responseCode == ObexHelper.OBEX_HTTP_CONTINUE)) {
|
||||
if (!mOperationDone) {
|
||||
mReplyHeader.responseCode = ResponseCodes.OBEX_HTTP_CONTINUE;
|
||||
while ((more) && (mReplyHeader.responseCode == ResponseCodes.OBEX_HTTP_CONTINUE)) {
|
||||
more = sendRequest(0x02);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if (replyHeaders.responseCode == ObexHelper.OBEX_HTTP_CONTINUE) {
|
||||
parent.sendRequest(0x82, null, replyHeaders, privateInput);
|
||||
if (mReplyHeader.responseCode == ResponseCodes.OBEX_HTTP_CONTINUE) {
|
||||
mParent.sendRequest(0x82, null, mReplyHeader, mPrivateInput);
|
||||
}
|
||||
|
||||
if (replyHeaders.responseCode != ObexHelper.OBEX_HTTP_CONTINUE) {
|
||||
isDone = true;
|
||||
if (mReplyHeader.responseCode != ResponseCodes.OBEX_HTTP_CONTINUE) {
|
||||
mOperationDone = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -697,45 +669,45 @@ public final class ClientOperation implements Operation, BaseStream {
|
||||
public synchronized boolean continueOperation(boolean sendEmpty, boolean inStream)
|
||||
throws IOException {
|
||||
|
||||
if (isGet) {
|
||||
if ((inStream) && (!isDone)) {
|
||||
if (mGetOperation) {
|
||||
if ((inStream) && (!mOperationDone)) {
|
||||
// to deal with inputstream in get operation
|
||||
parent.sendRequest(0x83, null, replyHeaders, privateInput);
|
||||
mParent.sendRequest(0x83, null, mReplyHeader, mPrivateInput);
|
||||
/*
|
||||
* Determine if that was not the last packet in the operation
|
||||
*/
|
||||
if (replyHeaders.responseCode != ObexHelper.OBEX_HTTP_CONTINUE) {
|
||||
isDone = true;
|
||||
if (mReplyHeader.responseCode != ResponseCodes.OBEX_HTTP_CONTINUE) {
|
||||
mOperationDone = true;
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
} else if ((!inStream) && (!isDone)) {
|
||||
} else if ((!inStream) && (!mOperationDone)) {
|
||||
// to deal with outputstream in get operation
|
||||
|
||||
if (privateInput == null) {
|
||||
privateInput = new PrivateInputStream(this);
|
||||
if (mPrivateInput == null) {
|
||||
mPrivateInput = new PrivateInputStream(this);
|
||||
}
|
||||
sendRequest(0x03);
|
||||
return true;
|
||||
|
||||
} else if (isDone) {
|
||||
} else if (mOperationDone) {
|
||||
return false;
|
||||
}
|
||||
|
||||
} else {
|
||||
if ((!inStream) && (!isDone)) {
|
||||
if ((!inStream) && (!mOperationDone)) {
|
||||
// to deal with outputstream in put operation
|
||||
if (replyHeaders.responseCode == -1) {
|
||||
replyHeaders.responseCode = ObexHelper.OBEX_HTTP_CONTINUE;
|
||||
if (mReplyHeader.responseCode == -1) {
|
||||
mReplyHeader.responseCode = ResponseCodes.OBEX_HTTP_CONTINUE;
|
||||
}
|
||||
sendRequest(0x02);
|
||||
return true;
|
||||
} else if ((inStream) && (!isDone)) {
|
||||
} else if ((inStream) && (!mOperationDone)) {
|
||||
// How to deal with inputstream in put operation ?
|
||||
return false;
|
||||
|
||||
} else if (isDone) {
|
||||
} else if (mOperationDone) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -752,23 +724,23 @@ public final class ClientOperation implements Operation, BaseStream {
|
||||
* @throws IOException if an IO error occurs
|
||||
*/
|
||||
public void streamClosed(boolean inStream) throws IOException {
|
||||
if (!isGet) {
|
||||
if ((!inStream) && (!isDone)) {
|
||||
if (!mGetOperation) {
|
||||
if ((!inStream) && (!mOperationDone)) {
|
||||
// to deal with outputstream in put operation
|
||||
|
||||
boolean more = true;
|
||||
|
||||
if ((privateOutput != null) && (privateOutput.size() <= 0)) {
|
||||
byte[] headerArray = ObexHelper.createHeader(requestHeaders, false);
|
||||
if ((mPrivateOutput != null) && (mPrivateOutput.size() <= 0)) {
|
||||
byte[] headerArray = ObexHelper.createHeader(mRequestHeader, false);
|
||||
if (headerArray.length <= 0)
|
||||
more = false;
|
||||
}
|
||||
// If have not sent any data so send all now
|
||||
if (replyHeaders.responseCode == -1) {
|
||||
replyHeaders.responseCode = ObexHelper.OBEX_HTTP_CONTINUE;
|
||||
if (mReplyHeader.responseCode == -1) {
|
||||
mReplyHeader.responseCode = ResponseCodes.OBEX_HTTP_CONTINUE;
|
||||
}
|
||||
|
||||
while ((more) && (replyHeaders.responseCode == ObexHelper.OBEX_HTTP_CONTINUE)) {
|
||||
while ((more) && (mReplyHeader.responseCode == ResponseCodes.OBEX_HTTP_CONTINUE)) {
|
||||
more = sendRequest(0x02);
|
||||
}
|
||||
|
||||
@@ -777,61 +749,60 @@ public final class ClientOperation implements Operation, BaseStream {
|
||||
* only have a single reply to send. so we don't need the while
|
||||
* loop.
|
||||
*/
|
||||
while (replyHeaders.responseCode == ObexHelper.OBEX_HTTP_CONTINUE) {
|
||||
while (mReplyHeader.responseCode == ResponseCodes.OBEX_HTTP_CONTINUE) {
|
||||
|
||||
sendRequest(0x82);
|
||||
}
|
||||
isDone = true;
|
||||
} else if ((inStream) && (isDone)) {
|
||||
mOperationDone = true;
|
||||
} else if ((inStream) && (mOperationDone)) {
|
||||
// how to deal with input stream in put stream ?
|
||||
isDone = true;
|
||||
mOperationDone = true;
|
||||
}
|
||||
} else {
|
||||
isValidateConnected = false;
|
||||
if ((inStream) && (!isDone)) {
|
||||
if ((inStream) && (!mOperationDone)) {
|
||||
|
||||
// to deal with inputstream in get operation
|
||||
// Have not sent any data so send it all now
|
||||
|
||||
if (replyHeaders.responseCode == -1) {
|
||||
replyHeaders.responseCode = ObexHelper.OBEX_HTTP_CONTINUE;
|
||||
if (mReplyHeader.responseCode == -1) {
|
||||
mReplyHeader.responseCode = ResponseCodes.OBEX_HTTP_CONTINUE;
|
||||
}
|
||||
|
||||
while (replyHeaders.responseCode == ObexHelper.OBEX_HTTP_CONTINUE) {
|
||||
while (mReplyHeader.responseCode == ResponseCodes.OBEX_HTTP_CONTINUE) {
|
||||
if (!sendRequest(0x83)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
while (replyHeaders.responseCode == ObexHelper.OBEX_HTTP_CONTINUE) {
|
||||
parent.sendRequest(0x83, null, replyHeaders, privateInput);
|
||||
while (mReplyHeader.responseCode == ResponseCodes.OBEX_HTTP_CONTINUE) {
|
||||
mParent.sendRequest(0x83, null, mReplyHeader, mPrivateInput);
|
||||
}
|
||||
isDone = true;
|
||||
} else if ((!inStream) && (!isDone)) {
|
||||
mOperationDone = true;
|
||||
} else if ((!inStream) && (!mOperationDone)) {
|
||||
// to deal with outputstream in get operation
|
||||
// part of the data may have been sent in continueOperation.
|
||||
|
||||
boolean more = true;
|
||||
|
||||
if ((privateOutput != null) && (privateOutput.size() <= 0)) {
|
||||
byte[] headerArray = ObexHelper.createHeader(requestHeaders, false);
|
||||
if ((mPrivateOutput != null) && (mPrivateOutput.size() <= 0)) {
|
||||
byte[] headerArray = ObexHelper.createHeader(mRequestHeader, false);
|
||||
if (headerArray.length <= 0)
|
||||
more = false;
|
||||
}
|
||||
|
||||
if (privateInput == null) {
|
||||
privateInput = new PrivateInputStream(this);
|
||||
if (mPrivateInput == null) {
|
||||
mPrivateInput = new PrivateInputStream(this);
|
||||
}
|
||||
if ((privateOutput != null) && (privateOutput.size() <= 0))
|
||||
if ((mPrivateOutput != null) && (mPrivateOutput.size() <= 0))
|
||||
more = false;
|
||||
|
||||
replyHeaders.responseCode = ObexHelper.OBEX_HTTP_CONTINUE;
|
||||
while ((more) && (replyHeaders.responseCode == ObexHelper.OBEX_HTTP_CONTINUE)) {
|
||||
mReplyHeader.responseCode = ResponseCodes.OBEX_HTTP_CONTINUE;
|
||||
while ((more) && (mReplyHeader.responseCode == ResponseCodes.OBEX_HTTP_CONTINUE)) {
|
||||
more = sendRequest(0x03);
|
||||
}
|
||||
sendRequest(0x83);
|
||||
// parent.sendRequest(0x83, null, replyHeaders, privateInput);
|
||||
if (replyHeaders.responseCode != ObexHelper.OBEX_HTTP_CONTINUE) {
|
||||
isDone = true;
|
||||
if (mReplyHeader.responseCode != ResponseCodes.OBEX_HTTP_CONTINUE) {
|
||||
mOperationDone = true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -38,13 +38,11 @@ import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
|
||||
/**
|
||||
* This class implements the <code>Operation</code> interface. It will read
|
||||
* and write data via puts and gets.
|
||||
* This class in an implementation of the OBEX ClientSession.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public final class ClientSession implements ObexSession {
|
||||
private Authenticator mAuthenticator;
|
||||
public final class ClientSession extends ObexSession {
|
||||
|
||||
private boolean mOpen;
|
||||
|
||||
@@ -53,8 +51,6 @@ public final class ClientSession implements ObexSession {
|
||||
|
||||
private byte[] mConnectionId = null;
|
||||
|
||||
private byte[] mChallengeDigest = null;
|
||||
|
||||
/*
|
||||
* The max Packet size must be at least 256 according to the OBEX
|
||||
* specification.
|
||||
@@ -67,14 +63,14 @@ public final class ClientSession implements ObexSession {
|
||||
|
||||
private final OutputStream mOutput;
|
||||
|
||||
public ClientSession(ObexTransport trans) throws IOException {
|
||||
public ClientSession(final ObexTransport trans) throws IOException {
|
||||
mInput = trans.openInputStream();
|
||||
mOutput = trans.openOutputStream();
|
||||
mOpen = true;
|
||||
mRequestActive = false;
|
||||
}
|
||||
|
||||
public HeaderSet connect(HeaderSet header) throws IOException {
|
||||
public HeaderSet connect(final HeaderSet header) throws IOException {
|
||||
ensureOpen();
|
||||
if (mObexConnected) {
|
||||
throw new IOException("Already connected to server");
|
||||
@@ -119,7 +115,7 @@ public final class ClientSession implements ObexSession {
|
||||
}
|
||||
|
||||
HeaderSet returnHeaderSet = new HeaderSet();
|
||||
sendRequest(0x80, requestPacket, returnHeaderSet, null);
|
||||
sendRequest(ObexHelper.OBEX_OPCODE_CONNECT, requestPacket, returnHeaderSet, null);
|
||||
|
||||
/*
|
||||
* Read the response from the OBEX server.
|
||||
@@ -147,21 +143,23 @@ public final class ClientSession implements ObexSession {
|
||||
|
||||
ensureOpen();
|
||||
|
||||
HeaderSet head;
|
||||
if (header == null) {
|
||||
header = new HeaderSet();
|
||||
head = new HeaderSet();
|
||||
} else {
|
||||
if (header.nonce != null) {
|
||||
head = header;
|
||||
if (head.nonce != null) {
|
||||
mChallengeDigest = new byte[16];
|
||||
System.arraycopy(header.nonce, 0, mChallengeDigest, 0, 16);
|
||||
System.arraycopy(head.nonce, 0, mChallengeDigest, 0, 16);
|
||||
}
|
||||
}
|
||||
// Add the connection ID if one exists
|
||||
if (mConnectionId != null) {
|
||||
header.connectionID = new byte[4];
|
||||
System.arraycopy(mConnectionId, 0, header.connectionID, 0, 4);
|
||||
head.mConnectionID = new byte[4];
|
||||
System.arraycopy(mConnectionId, 0, head.mConnectionID, 0, 4);
|
||||
}
|
||||
|
||||
return new ClientOperation(mInput, maxPacketSize, this, header, true);
|
||||
return new ClientOperation(maxPacketSize, this, head, true);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -178,7 +176,7 @@ public final class ClientSession implements ObexSession {
|
||||
|
||||
Operation op = put(header);
|
||||
op.getResponseCode();
|
||||
HeaderSet returnValue = op.getReceivedHeaders();
|
||||
HeaderSet returnValue = op.getReceivedHeader();
|
||||
op.close();
|
||||
|
||||
return returnValue;
|
||||
@@ -200,8 +198,8 @@ public final class ClientSession implements ObexSession {
|
||||
}
|
||||
// Add the connection ID if one exists
|
||||
if (mConnectionId != null) {
|
||||
header.connectionID = new byte[4];
|
||||
System.arraycopy(mConnectionId, 0, header.connectionID, 0, 4);
|
||||
header.mConnectionID = new byte[4];
|
||||
System.arraycopy(mConnectionId, 0, header.mConnectionID, 0, 4);
|
||||
}
|
||||
head = ObexHelper.createHeader(header, false);
|
||||
|
||||
@@ -212,13 +210,13 @@ public final class ClientSession implements ObexSession {
|
||||
// Add the connection ID if one exists
|
||||
if (mConnectionId != null) {
|
||||
head = new byte[5];
|
||||
head[0] = (byte)0xCB;
|
||||
head[0] = (byte)HeaderSet.CONNECTION_ID;
|
||||
System.arraycopy(mConnectionId, 0, head, 1, 4);
|
||||
}
|
||||
}
|
||||
|
||||
HeaderSet returnHeaderSet = new HeaderSet();
|
||||
sendRequest(0x81, head, returnHeaderSet, null);
|
||||
sendRequest(ObexHelper.OBEX_OPCODE_DISCONNECT, head, returnHeaderSet, null);
|
||||
|
||||
/*
|
||||
* An OBEX DISCONNECT reply from the server:
|
||||
@@ -253,36 +251,36 @@ public final class ClientSession implements ObexSession {
|
||||
setRequestActive();
|
||||
|
||||
ensureOpen();
|
||||
|
||||
HeaderSet head;
|
||||
if (header == null) {
|
||||
header = new HeaderSet();
|
||||
head = new HeaderSet();
|
||||
} else {
|
||||
// when auth is initated by client ,save the digest
|
||||
if (header.nonce != null) {
|
||||
head = header;
|
||||
// when auth is initiated by client ,save the digest
|
||||
if (head.nonce != null) {
|
||||
mChallengeDigest = new byte[16];
|
||||
System.arraycopy(header.nonce, 0, mChallengeDigest, 0, 16);
|
||||
System.arraycopy(head.nonce, 0, mChallengeDigest, 0, 16);
|
||||
}
|
||||
}
|
||||
|
||||
// Add the connection ID if one exists
|
||||
if (mConnectionId != null) {
|
||||
|
||||
header.connectionID = new byte[4];
|
||||
System.arraycopy(mConnectionId, 0, header.connectionID, 0, 4);
|
||||
head.mConnectionID = new byte[4];
|
||||
System.arraycopy(mConnectionId, 0, head.mConnectionID, 0, 4);
|
||||
}
|
||||
|
||||
return new ClientOperation(mInput, maxPacketSize, this, header, false);
|
||||
return new ClientOperation(maxPacketSize, this, head, false);
|
||||
}
|
||||
|
||||
public void setAuthenticator(Authenticator auth) {
|
||||
public void setAuthenticator(Authenticator auth) throws IOException {
|
||||
if (auth == null) {
|
||||
throw new NullPointerException("Authenticator may not be null");
|
||||
throw new IOException("Authenticator may not be null");
|
||||
}
|
||||
mAuthenticator = auth;
|
||||
}
|
||||
|
||||
public HeaderSet setPath(HeaderSet header, boolean backup, boolean create)
|
||||
throws IOException {
|
||||
public HeaderSet setPath(HeaderSet header, boolean backup, boolean create) throws IOException {
|
||||
if (!mObexConnected) {
|
||||
throw new IOException("Not connected to the server");
|
||||
}
|
||||
@@ -291,29 +289,30 @@ public final class ClientSession implements ObexSession {
|
||||
|
||||
int totalLength = 2;
|
||||
byte[] head = null;
|
||||
|
||||
HeaderSet headset;
|
||||
if (header == null) {
|
||||
header = new HeaderSet();
|
||||
headset = new HeaderSet();
|
||||
} else {
|
||||
if (header.nonce != null) {
|
||||
headset = header;
|
||||
if (headset.nonce != null) {
|
||||
mChallengeDigest = new byte[16];
|
||||
System.arraycopy(header.nonce, 0, mChallengeDigest, 0, 16);
|
||||
System.arraycopy(headset.nonce, 0, mChallengeDigest, 0, 16);
|
||||
}
|
||||
}
|
||||
|
||||
// when auth is initiated by client ,save the digest
|
||||
if (header.nonce != null) {
|
||||
if (headset.nonce != null) {
|
||||
mChallengeDigest = new byte[16];
|
||||
System.arraycopy(header.nonce, 0, mChallengeDigest, 0, 16);
|
||||
System.arraycopy(headset.nonce, 0, mChallengeDigest, 0, 16);
|
||||
}
|
||||
|
||||
// Add the connection ID if one exists
|
||||
if (mConnectionId != null) {
|
||||
header.connectionID = new byte[4];
|
||||
System.arraycopy(mConnectionId, 0, header.connectionID, 0, 4);
|
||||
headset.mConnectionID = new byte[4];
|
||||
System.arraycopy(mConnectionId, 0, headset.mConnectionID, 0, 4);
|
||||
}
|
||||
|
||||
head = ObexHelper.createHeader(header, false);
|
||||
head = ObexHelper.createHeader(headset, false);
|
||||
totalLength += head.length;
|
||||
|
||||
if (totalLength > maxPacketSize) {
|
||||
@@ -345,12 +344,12 @@ public final class ClientSession implements ObexSession {
|
||||
byte[] packet = new byte[totalLength];
|
||||
packet[0] = (byte)flags;
|
||||
packet[1] = (byte)0x00;
|
||||
if (header != null) {
|
||||
if (headset != null) {
|
||||
System.arraycopy(head, 0, packet, 2, head.length);
|
||||
}
|
||||
|
||||
HeaderSet returnHeaderSet = new HeaderSet();
|
||||
sendRequest(0x85, packet, returnHeaderSet, null);
|
||||
sendRequest(ObexHelper.OBEX_OPCODE_SETPATH, packet, returnHeaderSet, null);
|
||||
|
||||
/*
|
||||
* An OBEX SETPATH reply from the server:
|
||||
@@ -380,7 +379,7 @@ public final class ClientSession implements ObexSession {
|
||||
* Allows Put and get operation objects to tell this object when they are
|
||||
* done.
|
||||
*/
|
||||
/*package*/ synchronized void setRequestInactive() {
|
||||
/*package*/synchronized void setRequestInactive() {
|
||||
mRequestActive = false;
|
||||
}
|
||||
|
||||
@@ -401,7 +400,7 @@ public final class ClientSession implements ObexSession {
|
||||
* headers (i.e. authentication challenge or authentication response) are
|
||||
* received, they will be processed.
|
||||
*
|
||||
* @param code the type of request to send to the client
|
||||
* @param opCode the type of request to send to the client
|
||||
*
|
||||
* @param head the headers to send to the server
|
||||
*
|
||||
@@ -419,7 +418,7 @@ public final class ClientSession implements ObexSession {
|
||||
*
|
||||
* @throws IOException if an IO error occurs
|
||||
*/
|
||||
public boolean sendRequest(int code, byte[] head, HeaderSet header,
|
||||
public boolean sendRequest(int opCode, byte[] head, HeaderSet header,
|
||||
PrivateInputStream privateInput) throws IOException {
|
||||
//check header length with local max size
|
||||
if (head != null) {
|
||||
@@ -427,10 +426,10 @@ public final class ClientSession implements ObexSession {
|
||||
throw new IOException("header too large ");
|
||||
}
|
||||
}
|
||||
//byte[] nonce;
|
||||
|
||||
int bytesReceived;
|
||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||
out.write((byte)code);
|
||||
out.write((byte)opCode);
|
||||
|
||||
// Determine if there are any headers to send
|
||||
if (head == null) {
|
||||
@@ -453,10 +452,12 @@ public final class ClientSession implements ObexSession {
|
||||
if (length > ObexHelper.MAX_PACKET_SIZE_INT) {
|
||||
throw new IOException("Packet received exceeds packet size limit");
|
||||
}
|
||||
if (length > 3) {
|
||||
if (length > ObexHelper.BASE_PACKET_LENGTH) {
|
||||
byte[] data = null;
|
||||
if (code == 0x80) {
|
||||
if (opCode == ObexHelper.OBEX_OPCODE_CONNECT) {
|
||||
@SuppressWarnings("unused")
|
||||
int version = mInput.read();
|
||||
@SuppressWarnings("unused")
|
||||
int flags = mInput.read();
|
||||
maxPacketSize = (mInput.read() << 8) + mInput.read();
|
||||
|
||||
@@ -483,7 +484,7 @@ public final class ClientSession implements ObexSession {
|
||||
while (bytesReceived != (length - 3)) {
|
||||
bytesReceived += mInput.read(data, bytesReceived, data.length - bytesReceived);
|
||||
}
|
||||
if (code == 0xFF) {
|
||||
if (opCode == ObexHelper.OBEX_OPCODE_ABORT) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -493,33 +494,33 @@ public final class ClientSession implements ObexSession {
|
||||
privateInput.writeBytes(body, 1);
|
||||
}
|
||||
|
||||
if (header.connectionID != null) {
|
||||
if (header.mConnectionID != null) {
|
||||
mConnectionId = new byte[4];
|
||||
System.arraycopy(header.connectionID, 0, mConnectionId, 0, 4);
|
||||
System.arraycopy(header.mConnectionID, 0, mConnectionId, 0, 4);
|
||||
}
|
||||
|
||||
if (header.authResp != null) {
|
||||
if (!handleAuthResp(header.authResp)) {
|
||||
if (header.mAuthResp != null) {
|
||||
if (!handleAuthResp(header.mAuthResp)) {
|
||||
setRequestInactive();
|
||||
throw new IOException("Authentication Failed");
|
||||
}
|
||||
}
|
||||
|
||||
if ((header.responseCode == ResponseCodes.OBEX_HTTP_UNAUTHORIZED)
|
||||
&& (header.authChall != null)) {
|
||||
&& (header.mAuthChall != null)) {
|
||||
|
||||
if (handleAuthChall(header)) {
|
||||
out.write((byte)0x4E);
|
||||
out.write((byte)((header.authResp.length + 3) >> 8));
|
||||
out.write((byte)(header.authResp.length + 3));
|
||||
out.write(header.authResp);
|
||||
header.authChall = null;
|
||||
header.authResp = null;
|
||||
out.write((byte)HeaderSet.AUTH_RESPONSE);
|
||||
out.write((byte)((header.mAuthResp.length + 3) >> 8));
|
||||
out.write((byte)(header.mAuthResp.length + 3));
|
||||
out.write(header.mAuthResp);
|
||||
header.mAuthChall = null;
|
||||
header.mAuthResp = null;
|
||||
|
||||
byte[] sendHeaders = new byte[out.size() - 3];
|
||||
System.arraycopy(out.toByteArray(), 3, sendHeaders, 0, sendHeaders.length);
|
||||
|
||||
return sendRequest(code, sendHeaders, header, privateInput);
|
||||
return sendRequest(opCode, sendHeaders, header, privateInput);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -527,194 +528,6 @@ public final class ClientSession implements ObexSession {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the client received an authentication challenge header. This
|
||||
* will cause the authenticator to handle the authentication challenge.
|
||||
*
|
||||
* @param header the header with the authentication challenge
|
||||
*
|
||||
* @return <code>true</code> if the last request should be resent;
|
||||
* <code>false</code> if the last request should not be resent
|
||||
*/
|
||||
protected boolean handleAuthChall(HeaderSet header) {
|
||||
|
||||
if (mAuthenticator == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* An authentication challenge is made up of one required and two
|
||||
* optional tag length value triplets. The tag 0x00 is required to be
|
||||
* in the authentication challenge and it represents the challenge
|
||||
* digest that was received. The tag 0x01 is the options tag. This
|
||||
* tag tracks if user ID is required and if full access will be
|
||||
* granted. The tag 0x02 is the realm, which provides a description of
|
||||
* which user name and password to use.
|
||||
*/
|
||||
byte[] challenge = ObexHelper.getTagValue((byte)0x00, header.authChall);
|
||||
byte[] option = ObexHelper.getTagValue((byte)0x01, header.authChall);
|
||||
byte[] description = ObexHelper.getTagValue((byte)0x02, header.authChall);
|
||||
|
||||
String realm = "";
|
||||
if (description != null) {
|
||||
byte[] realmString = new byte[description.length - 1];
|
||||
System.arraycopy(description, 1, realmString, 0, realmString.length);
|
||||
|
||||
switch (description[0] & 0xFF) {
|
||||
|
||||
case 0x00:
|
||||
// ASCII encoding
|
||||
// Fall through
|
||||
case 0x01:
|
||||
// ISO-8859-1 encoding
|
||||
try {
|
||||
realm = new String(realmString, "ISO8859_1");
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("Unsupported Encoding Scheme");
|
||||
}
|
||||
break;
|
||||
|
||||
case 0xFF:
|
||||
// UNICODE Encoding
|
||||
realm = ObexHelper.convertToUnicode(realmString, false);
|
||||
break;
|
||||
|
||||
case 0x02:
|
||||
// ISO-8859-2 encoding
|
||||
// Fall through
|
||||
case 0x03:
|
||||
// ISO-8859-3 encoding
|
||||
// Fall through
|
||||
case 0x04:
|
||||
// ISO-8859-4 encoding
|
||||
// Fall through
|
||||
case 0x05:
|
||||
// ISO-8859-5 encoding
|
||||
// Fall through
|
||||
case 0x06:
|
||||
// ISO-8859-6 encoding
|
||||
// Fall through
|
||||
case 0x07:
|
||||
// ISO-8859-7 encoding
|
||||
// Fall through
|
||||
case 0x08:
|
||||
// ISO-8859-8 encoding
|
||||
// Fall through
|
||||
case 0x09:
|
||||
// ISO-8859-9 encoding
|
||||
// Fall through
|
||||
default:
|
||||
throw new RuntimeException("Unsupported Encoding Scheme");
|
||||
}
|
||||
}
|
||||
|
||||
boolean isUserIDRequired = false;
|
||||
boolean isFullAccess = true;
|
||||
if (option != null) {
|
||||
if ((option[0] & 0x01) != 0) {
|
||||
isUserIDRequired = true;
|
||||
}
|
||||
|
||||
if ((option[0] & 0x02) != 0) {
|
||||
isFullAccess = false;
|
||||
}
|
||||
}
|
||||
|
||||
PasswordAuthentication result = null;
|
||||
header.authChall = null;
|
||||
|
||||
try {
|
||||
result = mAuthenticator.onAuthenticationChallenge(realm, isUserIDRequired, isFullAccess);
|
||||
} catch (Exception e) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* If no password was provided then do not resend the request
|
||||
*/
|
||||
if (result == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
byte[] password = result.getPassword();
|
||||
if (password == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
byte[] userName = result.getUserName();
|
||||
|
||||
/*
|
||||
* Create the authentication response header. It includes 1 required
|
||||
* and 2 option tag length value triples. The required triple has a
|
||||
* tag of 0x00 and is the response digest. The first optional tag is
|
||||
* 0x01 and represents the user ID. If no user ID is provided, then
|
||||
* no user ID will be sent. The second optional tag is 0x02 and is the
|
||||
* challenge that was received. This will always be sent
|
||||
*/
|
||||
if (userName != null) {
|
||||
header.authResp = new byte[38 + userName.length];
|
||||
header.authResp[36] = (byte)0x01;
|
||||
header.authResp[37] = (byte)userName.length;
|
||||
System.arraycopy(userName, 0, header.authResp, 38, userName.length);
|
||||
} else {
|
||||
header.authResp = new byte[36];
|
||||
}
|
||||
|
||||
// Create the secret String
|
||||
byte[] digest = new byte[challenge.length + password.length];
|
||||
System.arraycopy(challenge, 0, digest, 0, challenge.length);
|
||||
System.arraycopy(password, 0, digest, challenge.length, password.length);
|
||||
|
||||
// Add the Response Digest
|
||||
header.authResp[0] = (byte)0x00;
|
||||
header.authResp[1] = (byte)0x10;
|
||||
|
||||
byte[] responseDigest = ObexHelper.computeMd5Hash(digest);
|
||||
System.arraycopy(responseDigest, 0, header.authResp, 2, 16);
|
||||
|
||||
// Add the challenge
|
||||
header.authResp[18] = (byte)0x02;
|
||||
header.authResp[19] = (byte)0x10;
|
||||
System.arraycopy(challenge, 0, header.authResp, 20, 16);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the client received an authentication response header. This
|
||||
* will cause the authenticator to handle the authentication response.
|
||||
*
|
||||
* @param authResp the authentication response
|
||||
*
|
||||
* @return <code>true</code> if the response passed; <code>false</code> if
|
||||
* the response failed
|
||||
*/
|
||||
protected boolean handleAuthResp(byte[] authResp) {
|
||||
if (mAuthenticator == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
byte[] correctPassword = mAuthenticator.onAuthenticationResponse(ObexHelper.getTagValue(
|
||||
(byte)0x01, authResp));
|
||||
if (correctPassword == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
byte[] temp = new byte[correctPassword.length + 16];
|
||||
System.arraycopy(mChallengeDigest, 0, temp, 0, 16);
|
||||
System.arraycopy(correctPassword, 0, temp, 16, correctPassword.length);
|
||||
|
||||
byte[] correctResponse = ObexHelper.computeMd5Hash(temp);
|
||||
byte[] actualResponse = ObexHelper.getTagValue((byte)0x00, authResp);
|
||||
for (int i = 0; i < 16; i++) {
|
||||
if (correctResponse[i] != actualResponse[i]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public void close() throws IOException {
|
||||
mOpen = false;
|
||||
mInput.close();
|
||||
|
||||
@@ -117,6 +117,20 @@ public final class HeaderSet {
|
||||
*/
|
||||
public static final int HTTP = 0x47;
|
||||
|
||||
/**
|
||||
* Represents the OBEX BODY header.
|
||||
* <P>
|
||||
* The value of <code>BODY</code> is 0x48 (72).
|
||||
*/
|
||||
public static final int BODY = 0x48;
|
||||
|
||||
/**
|
||||
* Represents the OBEX End of BODY header.
|
||||
* <P>
|
||||
* The value of <code>BODY</code> is 0x49 (73).
|
||||
*/
|
||||
public static final int END_OF_BODY = 0x49;
|
||||
|
||||
/**
|
||||
* Represents the OBEX Who header. Identifies the OBEX application to
|
||||
* determine if the two peers are talking to each other.
|
||||
@@ -126,12 +140,13 @@ public final class HeaderSet {
|
||||
public static final int WHO = 0x4A;
|
||||
|
||||
/**
|
||||
* Represents the OBEX Object Class header. This header specifies the
|
||||
* OBEX object class of the object.
|
||||
* Represents the OBEX Connection ID header. Identifies used for OBEX
|
||||
* connection multiplexing.
|
||||
* <P>
|
||||
* The value of <code>OBJECT_CLASS</code> is 0x4F (79).
|
||||
* The value of <code>CONNECTION_ID</code> is 0xCB (203).
|
||||
*/
|
||||
public static final int OBJECT_CLASS = 0x4F;
|
||||
|
||||
public static final int CONNECTION_ID = 0xCB;
|
||||
|
||||
/**
|
||||
* Represents the OBEX Application Parameter header. This header specifies
|
||||
@@ -141,49 +156,71 @@ public final class HeaderSet {
|
||||
*/
|
||||
public static final int APPLICATION_PARAMETER = 0x4C;
|
||||
|
||||
private Long count; // 4 byte unsigned integer
|
||||
/**
|
||||
* Represents the OBEX authentication digest-challenge.
|
||||
* <P>
|
||||
* The value of <code>AUTH_CHALLENGE</code> is 0x4D (77).
|
||||
*/
|
||||
public static final int AUTH_CHALLENGE = 0x4D;
|
||||
|
||||
private String name; // null terminated Unicode text string
|
||||
/**
|
||||
* Represents the OBEX authentication digest-response.
|
||||
* <P>
|
||||
* The value of <code>AUTH_RESPONSE</code> is 0x4E (78).
|
||||
*/
|
||||
public static final int AUTH_RESPONSE = 0x4E;
|
||||
|
||||
private String type; // null terminated ASCII text string
|
||||
/**
|
||||
* Represents the OBEX Object Class header. This header specifies the
|
||||
* OBEX object class of the object.
|
||||
* <P>
|
||||
* The value of <code>OBJECT_CLASS</code> is 0x4F (79).
|
||||
*/
|
||||
public static final int OBJECT_CLASS = 0x4F;
|
||||
|
||||
private Long length; // 4 byte unsigend integer
|
||||
private Long mCount; // 4 byte unsigned integer
|
||||
|
||||
private Calendar isoTime; // String of the form YYYYMMDDTHHMMSSZ
|
||||
private String mName; // null terminated Unicode text string
|
||||
|
||||
private Calendar byteTime; // 4 byte unsigned integer
|
||||
private String mType; // null terminated ASCII text string
|
||||
|
||||
private String description; // null terminated Unicode text String
|
||||
private Long mLength; // 4 byte unsigend integer
|
||||
|
||||
private byte[] target; // byte sequence
|
||||
private Calendar mIsoTime; // String of the form YYYYMMDDTHHMMSSZ
|
||||
|
||||
private byte[] http; // byte sequence
|
||||
private Calendar mByteTime; // 4 byte unsigned integer
|
||||
|
||||
private byte[] who; // length prefixed byte sequence
|
||||
private String mDescription; // null terminated Unicode text String
|
||||
|
||||
private byte[] appParam; // byte sequence of the form tag length value
|
||||
private byte[] mTarget; // byte sequence
|
||||
|
||||
public byte[] authChall; // The authentication challenge header
|
||||
private byte[] mHttpHeader; // byte sequence
|
||||
|
||||
public byte[] authResp; // The authentication response header
|
||||
private byte[] mWho; // length prefixed byte sequence
|
||||
|
||||
public byte[] connectionID; // THe connection ID
|
||||
private byte[] mAppParam; // byte sequence of the form tag length value
|
||||
|
||||
private byte[] objectClass; // byte sequence
|
||||
public byte[] mAuthChall; // The authentication challenge header
|
||||
|
||||
private String[] unicodeUserDefined; //null terminated unicode string
|
||||
public byte[] mAuthResp; // The authentication response header
|
||||
|
||||
private byte[][] sequenceUserDefined; // byte sequence user defined
|
||||
public byte[] mConnectionID; // THe connection ID
|
||||
|
||||
private Byte[] byteUserDefined; // 1 byte
|
||||
private byte[] mObjectClass; // byte sequence
|
||||
|
||||
private Long[] integerUserDefined; // 4 byte unsigned integer
|
||||
private String[] mUnicodeUserDefined; //null terminated unicode string
|
||||
|
||||
/*package*/ int responseCode;
|
||||
private byte[][] mSequenceUserDefined; // byte sequence user defined
|
||||
|
||||
/*package*/ byte[] nonce;
|
||||
private Byte[] mByteUserDefined; // 1 byte
|
||||
|
||||
private final Random random;
|
||||
private Long[] mIntegerUserDefined; // 4 byte unsigned integer
|
||||
|
||||
/*package*/int responseCode;
|
||||
|
||||
/*package*/byte[] nonce;
|
||||
|
||||
private final Random mRandom;
|
||||
|
||||
/**
|
||||
* Creates new <code>HeaderSet</code> object.
|
||||
@@ -191,12 +228,12 @@ public final class HeaderSet {
|
||||
* @param size the max packet size for this connection
|
||||
*/
|
||||
public HeaderSet() {
|
||||
unicodeUserDefined = new String[16];
|
||||
sequenceUserDefined = new byte[16][];
|
||||
byteUserDefined = new Byte[16];
|
||||
integerUserDefined = new Long[16];
|
||||
mUnicodeUserDefined = new String[16];
|
||||
mSequenceUserDefined = new byte[16][];
|
||||
mByteUserDefined = new Byte[16];
|
||||
mIntegerUserDefined = new Long[16];
|
||||
responseCode = -1;
|
||||
random = new Random();
|
||||
mRandom = new Random();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -222,7 +259,7 @@ public final class HeaderSet {
|
||||
case COUNT:
|
||||
if (!(headerValue instanceof Long)) {
|
||||
if (headerValue == null) {
|
||||
count = null;
|
||||
mCount = null;
|
||||
break;
|
||||
}
|
||||
throw new IllegalArgumentException("Count must be a Long");
|
||||
@@ -231,24 +268,24 @@ public final class HeaderSet {
|
||||
if ((temp < 0L) || (temp > 0xFFFFFFFFL)) {
|
||||
throw new IllegalArgumentException("Count must be between 0 and 0xFFFFFFFF");
|
||||
}
|
||||
count = (Long)headerValue;
|
||||
mCount = (Long)headerValue;
|
||||
break;
|
||||
case NAME:
|
||||
if ((headerValue != null) && (!(headerValue instanceof String))) {
|
||||
throw new IllegalArgumentException("Name must be a String");
|
||||
}
|
||||
name = (String)headerValue;
|
||||
mName = (String)headerValue;
|
||||
break;
|
||||
case TYPE:
|
||||
if ((headerValue != null) && (!(headerValue instanceof String))) {
|
||||
throw new IllegalArgumentException("Type must be a String");
|
||||
}
|
||||
type = (String)headerValue;
|
||||
mType = (String)headerValue;
|
||||
break;
|
||||
case LENGTH:
|
||||
if (!(headerValue instanceof Long)) {
|
||||
if (headerValue == null) {
|
||||
length = null;
|
||||
mLength = null;
|
||||
break;
|
||||
}
|
||||
throw new IllegalArgumentException("Length must be a Long");
|
||||
@@ -257,84 +294,84 @@ public final class HeaderSet {
|
||||
if ((temp < 0L) || (temp > 0xFFFFFFFFL)) {
|
||||
throw new IllegalArgumentException("Length must be between 0 and 0xFFFFFFFF");
|
||||
}
|
||||
length = (Long)headerValue;
|
||||
mLength = (Long)headerValue;
|
||||
break;
|
||||
case TIME_ISO_8601:
|
||||
if ((headerValue != null) && (!(headerValue instanceof Calendar))) {
|
||||
throw new IllegalArgumentException("Time ISO 8601 must be a Calendar");
|
||||
}
|
||||
isoTime = (Calendar)headerValue;
|
||||
mIsoTime = (Calendar)headerValue;
|
||||
break;
|
||||
case TIME_4_BYTE:
|
||||
if ((headerValue != null) && (!(headerValue instanceof Calendar))) {
|
||||
throw new IllegalArgumentException("Time 4 Byte must be a Calendar");
|
||||
}
|
||||
byteTime = (Calendar)headerValue;
|
||||
mByteTime = (Calendar)headerValue;
|
||||
break;
|
||||
case DESCRIPTION:
|
||||
if ((headerValue != null) && (!(headerValue instanceof String))) {
|
||||
throw new IllegalArgumentException("Description must be a String");
|
||||
}
|
||||
description = (String)headerValue;
|
||||
mDescription = (String)headerValue;
|
||||
break;
|
||||
case TARGET:
|
||||
if (headerValue == null) {
|
||||
target = null;
|
||||
mTarget = null;
|
||||
} else {
|
||||
if (!(headerValue instanceof byte[])) {
|
||||
throw new IllegalArgumentException("Target must be a byte array");
|
||||
} else {
|
||||
target = new byte[((byte[])headerValue).length];
|
||||
System.arraycopy(headerValue, 0, target, 0, target.length);
|
||||
mTarget = new byte[((byte[])headerValue).length];
|
||||
System.arraycopy(headerValue, 0, mTarget, 0, mTarget.length);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case HTTP:
|
||||
if (headerValue == null) {
|
||||
http = null;
|
||||
mHttpHeader = null;
|
||||
} else {
|
||||
if (!(headerValue instanceof byte[])) {
|
||||
throw new IllegalArgumentException("HTTP must be a byte array");
|
||||
} else {
|
||||
http = new byte[((byte[])headerValue).length];
|
||||
System.arraycopy(headerValue, 0, http, 0, http.length);
|
||||
mHttpHeader = new byte[((byte[])headerValue).length];
|
||||
System.arraycopy(headerValue, 0, mHttpHeader, 0, mHttpHeader.length);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case WHO:
|
||||
if (headerValue == null) {
|
||||
who = null;
|
||||
mWho = null;
|
||||
} else {
|
||||
if (!(headerValue instanceof byte[])) {
|
||||
throw new IllegalArgumentException("WHO must be a byte array");
|
||||
} else {
|
||||
who = new byte[((byte[])headerValue).length];
|
||||
System.arraycopy(headerValue, 0, who, 0, who.length);
|
||||
mWho = new byte[((byte[])headerValue).length];
|
||||
System.arraycopy(headerValue, 0, mWho, 0, mWho.length);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case OBJECT_CLASS:
|
||||
if (headerValue == null) {
|
||||
objectClass = null;
|
||||
mObjectClass = null;
|
||||
} else {
|
||||
if (!(headerValue instanceof byte[])) {
|
||||
throw new IllegalArgumentException("Object Class must be a byte array");
|
||||
} else {
|
||||
objectClass = new byte[((byte[])headerValue).length];
|
||||
System.arraycopy(headerValue, 0, objectClass, 0, objectClass.length);
|
||||
mObjectClass = new byte[((byte[])headerValue).length];
|
||||
System.arraycopy(headerValue, 0, mObjectClass, 0, mObjectClass.length);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case APPLICATION_PARAMETER:
|
||||
if (headerValue == null) {
|
||||
appParam = null;
|
||||
mAppParam = null;
|
||||
} else {
|
||||
if (!(headerValue instanceof byte[])) {
|
||||
throw new IllegalArgumentException(
|
||||
"Application Parameter must be a byte array");
|
||||
} else {
|
||||
appParam = new byte[((byte[])headerValue).length];
|
||||
System.arraycopy(headerValue, 0, appParam, 0, appParam.length);
|
||||
mAppParam = new byte[((byte[])headerValue).length];
|
||||
System.arraycopy(headerValue, 0, mAppParam, 0, mAppParam.length);
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -345,7 +382,7 @@ public final class HeaderSet {
|
||||
throw new IllegalArgumentException(
|
||||
"Unicode String User Defined must be a String");
|
||||
}
|
||||
unicodeUserDefined[headerID - 0x30] = (String)headerValue;
|
||||
mUnicodeUserDefined[headerID - 0x30] = (String)headerValue;
|
||||
|
||||
break;
|
||||
}
|
||||
@@ -353,15 +390,15 @@ public final class HeaderSet {
|
||||
if ((headerID >= 0x70) && (headerID <= 0x7F)) {
|
||||
|
||||
if (headerValue == null) {
|
||||
sequenceUserDefined[headerID - 0x70] = null;
|
||||
mSequenceUserDefined[headerID - 0x70] = null;
|
||||
} else {
|
||||
if (!(headerValue instanceof byte[])) {
|
||||
throw new IllegalArgumentException(
|
||||
"Byte Sequence User Defined must be a byte array");
|
||||
} else {
|
||||
sequenceUserDefined[headerID - 0x70] = new byte[((byte[])headerValue).length];
|
||||
System.arraycopy(headerValue, 0, sequenceUserDefined[headerID - 0x70],
|
||||
0, sequenceUserDefined[headerID - 0x70].length);
|
||||
mSequenceUserDefined[headerID - 0x70] = new byte[((byte[])headerValue).length];
|
||||
System.arraycopy(headerValue, 0, mSequenceUserDefined[headerID - 0x70],
|
||||
0, mSequenceUserDefined[headerID - 0x70].length);
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -371,7 +408,7 @@ public final class HeaderSet {
|
||||
if ((headerValue != null) && (!(headerValue instanceof Byte))) {
|
||||
throw new IllegalArgumentException("ByteUser Defined must be a Byte");
|
||||
}
|
||||
byteUserDefined[headerID - 0xB0] = (Byte)headerValue;
|
||||
mByteUserDefined[headerID - 0xB0] = (Byte)headerValue;
|
||||
|
||||
break;
|
||||
}
|
||||
@@ -380,7 +417,7 @@ public final class HeaderSet {
|
||||
if ((headerID >= 0xF0) && (headerID <= 0xFF)) {
|
||||
if (!(headerValue instanceof Long)) {
|
||||
if (headerValue == null) {
|
||||
integerUserDefined[headerID - 0xF0] = null;
|
||||
mIntegerUserDefined[headerID - 0xF0] = null;
|
||||
break;
|
||||
}
|
||||
throw new IllegalArgumentException("Integer User Defined must be a Long");
|
||||
@@ -390,7 +427,7 @@ public final class HeaderSet {
|
||||
throw new IllegalArgumentException(
|
||||
"Integer User Defined must be between 0 and 0xFFFFFFFF");
|
||||
}
|
||||
integerUserDefined[headerID - 0xF0] = (Long)headerValue;
|
||||
mIntegerUserDefined[headerID - 0xF0] = (Long)headerValue;
|
||||
break;
|
||||
}
|
||||
throw new IllegalArgumentException("Invalid Header Identifier");
|
||||
@@ -417,45 +454,45 @@ public final class HeaderSet {
|
||||
|
||||
switch (headerID) {
|
||||
case COUNT:
|
||||
return count;
|
||||
return mCount;
|
||||
case NAME:
|
||||
return name;
|
||||
return mName;
|
||||
case TYPE:
|
||||
return type;
|
||||
return mType;
|
||||
case LENGTH:
|
||||
return length;
|
||||
return mLength;
|
||||
case TIME_ISO_8601:
|
||||
return isoTime;
|
||||
return mIsoTime;
|
||||
case TIME_4_BYTE:
|
||||
return byteTime;
|
||||
return mByteTime;
|
||||
case DESCRIPTION:
|
||||
return description;
|
||||
return mDescription;
|
||||
case TARGET:
|
||||
return target;
|
||||
return mTarget;
|
||||
case HTTP:
|
||||
return http;
|
||||
return mHttpHeader;
|
||||
case WHO:
|
||||
return who;
|
||||
return mWho;
|
||||
case OBJECT_CLASS:
|
||||
return objectClass;
|
||||
return mObjectClass;
|
||||
case APPLICATION_PARAMETER:
|
||||
return appParam;
|
||||
return mAppParam;
|
||||
default:
|
||||
// Verify that it was not a Unicode String user Defined
|
||||
if ((headerID >= 0x30) && (headerID <= 0x3F)) {
|
||||
return unicodeUserDefined[headerID - 0x30];
|
||||
return mUnicodeUserDefined[headerID - 0x30];
|
||||
}
|
||||
// Verify that it was not a byte sequence user defined header
|
||||
if ((headerID >= 0x70) && (headerID <= 0x7F)) {
|
||||
return sequenceUserDefined[headerID - 0x70];
|
||||
return mSequenceUserDefined[headerID - 0x70];
|
||||
}
|
||||
// Verify that it was not a byte user defined header
|
||||
if ((headerID >= 0xB0) && (headerID <= 0xBF)) {
|
||||
return byteUserDefined[headerID - 0xB0];
|
||||
return mByteUserDefined[headerID - 0xB0];
|
||||
}
|
||||
// Verify that it was not a itneger user defined header
|
||||
// Verify that it was not a integer user defined header
|
||||
if ((headerID >= 0xF0) && (headerID <= 0xFF)) {
|
||||
return integerUserDefined[headerID - 0xF0];
|
||||
return mIntegerUserDefined[headerID - 0xF0];
|
||||
}
|
||||
throw new IllegalArgumentException("Invalid Header Identifier");
|
||||
}
|
||||
@@ -478,63 +515,63 @@ public final class HeaderSet {
|
||||
public int[] getHeaderList() throws IOException {
|
||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||
|
||||
if (count != null) {
|
||||
if (mCount != null) {
|
||||
out.write(COUNT);
|
||||
}
|
||||
if (name != null) {
|
||||
if (mName != null) {
|
||||
out.write(NAME);
|
||||
}
|
||||
if (type != null) {
|
||||
if (mType != null) {
|
||||
out.write(TYPE);
|
||||
}
|
||||
if (length != null) {
|
||||
if (mLength != null) {
|
||||
out.write(LENGTH);
|
||||
}
|
||||
if (isoTime != null) {
|
||||
if (mIsoTime != null) {
|
||||
out.write(TIME_ISO_8601);
|
||||
}
|
||||
if (byteTime != null) {
|
||||
if (mByteTime != null) {
|
||||
out.write(TIME_4_BYTE);
|
||||
}
|
||||
if (description != null) {
|
||||
if (mDescription != null) {
|
||||
out.write(DESCRIPTION);
|
||||
}
|
||||
if (target != null) {
|
||||
if (mTarget != null) {
|
||||
out.write(TARGET);
|
||||
}
|
||||
if (http != null) {
|
||||
if (mHttpHeader != null) {
|
||||
out.write(HTTP);
|
||||
}
|
||||
if (who != null) {
|
||||
if (mWho != null) {
|
||||
out.write(WHO);
|
||||
}
|
||||
if (appParam != null) {
|
||||
if (mAppParam != null) {
|
||||
out.write(APPLICATION_PARAMETER);
|
||||
}
|
||||
if (objectClass != null) {
|
||||
if (mObjectClass != null) {
|
||||
out.write(OBJECT_CLASS);
|
||||
}
|
||||
|
||||
for (int i = 0x30; i < 0x40; i++) {
|
||||
if (unicodeUserDefined[i - 0x30] != null) {
|
||||
if (mUnicodeUserDefined[i - 0x30] != null) {
|
||||
out.write(i);
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0x70; i < 0x80; i++) {
|
||||
if (sequenceUserDefined[i - 0x70] != null) {
|
||||
if (mSequenceUserDefined[i - 0x70] != null) {
|
||||
out.write(i);
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0xB0; i < 0xC0; i++) {
|
||||
if (byteUserDefined[i - 0xB0] != null) {
|
||||
if (mByteUserDefined[i - 0xB0] != null) {
|
||||
out.write(i);
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0xF0; i < 0x100; i++) {
|
||||
if (integerUserDefined[i - 0xF0] != null) {
|
||||
if (mIntegerUserDefined[i - 0xF0] != null) {
|
||||
out.write(i);
|
||||
}
|
||||
}
|
||||
@@ -572,18 +609,20 @@ public final class HeaderSet {
|
||||
* @param access if <code>true</code> then full access will be granted if
|
||||
* successful; if <code>false</code> then read-only access will be granted
|
||||
* if successful
|
||||
* @throws IOException
|
||||
*/
|
||||
public void createAuthenticationChallenge(String realm, boolean userID, boolean access) {
|
||||
public void createAuthenticationChallenge(String realm, boolean userID, boolean access)
|
||||
throws IOException {
|
||||
|
||||
try {
|
||||
nonce = new byte[16];
|
||||
for (int i = 0; i < 16; i++) {
|
||||
nonce[i] = (byte)random.nextInt();
|
||||
nonce[i] = (byte)mRandom.nextInt();
|
||||
}
|
||||
|
||||
authChall = ObexHelper.computeAuthenticationChallenge(nonce, realm, access, userID);
|
||||
mAuthChall = ObexHelper.computeAuthenticationChallenge(nonce, realm, access, userID);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e.getMessage());
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -48,15 +48,17 @@ import java.util.TimeZone;
|
||||
*/
|
||||
public final class ObexHelper {
|
||||
|
||||
/** Prevent object construction of helper class */
|
||||
private ObexHelper() {}
|
||||
|
||||
/**
|
||||
* Defines the OBEX CONTINUE response code.
|
||||
* <P>
|
||||
* The value of <code>OBEX_HTTP_CONTINUE</code> is 0x90 (144).
|
||||
* Defines the basic packet length used by OBEX. Every OBEX packet has the
|
||||
* same basic format:<BR>
|
||||
* Byte 0: Request or Response Code
|
||||
* Byte 1&2: Length of the packet.
|
||||
*/
|
||||
public static final int OBEX_HTTP_CONTINUE = 0x90;
|
||||
public static final int BASE_PACKET_LENGTH = 3;
|
||||
|
||||
/** Prevent object construction of helper class */
|
||||
private ObexHelper() {
|
||||
}
|
||||
|
||||
/**
|
||||
* The maximum packet size for OBEX packets that this client can handle.
|
||||
@@ -73,6 +75,48 @@ public final class ObexHelper {
|
||||
*/
|
||||
public static final int MAX_PACKET_SIZE_INT = 0xFFFE;
|
||||
|
||||
public static final int OBEX_OPCODE_CONNECT = 0x80;
|
||||
|
||||
public static final int OBEX_OPCODE_DISCONNECT = 0x81;
|
||||
|
||||
public static final int OBEX_OPCODE_PUT = 0x02;
|
||||
|
||||
public static final int OBEX_OPCODE_PUT_FINAL = 0x82;
|
||||
|
||||
public static final int OBEX_OPCODE_GET = 0x03;
|
||||
|
||||
public static final int OBEX_OPCODE_GET_FINAL = 0x83;
|
||||
|
||||
public static final int OBEX_OPCODE_RESERVED = 0x04;
|
||||
|
||||
public static final int OBEX_OPCODE_RESERVED_FINAL = 0x84;
|
||||
|
||||
public static final int OBEX_OPCODE_SETPATH = 0x85;
|
||||
|
||||
public static final int OBEX_OPCODE_ABORT = 0xFF;
|
||||
|
||||
public static final int OBEX_AUTH_REALM_CHARSET_ASCII = 0x00;
|
||||
|
||||
public static final int OBEX_AUTH_REALM_CHARSET_ISO_8859_1 = 0x01;
|
||||
|
||||
public static final int OBEX_AUTH_REALM_CHARSET_ISO_8859_2 = 0x02;
|
||||
|
||||
public static final int OBEX_AUTH_REALM_CHARSET_ISO_8859_3 = 0x03;
|
||||
|
||||
public static final int OBEX_AUTH_REALM_CHARSET_ISO_8859_4 = 0x04;
|
||||
|
||||
public static final int OBEX_AUTH_REALM_CHARSET_ISO_8859_5 = 0x05;
|
||||
|
||||
public static final int OBEX_AUTH_REALM_CHARSET_ISO_8859_6 = 0x06;
|
||||
|
||||
public static final int OBEX_AUTH_REALM_CHARSET_ISO_8859_7 = 0x07;
|
||||
|
||||
public static final int OBEX_AUTH_REALM_CHARSET_ISO_8859_8 = 0x08;
|
||||
|
||||
public static final int OBEX_AUTH_REALM_CHARSET_ISO_8859_9 = 0x09;
|
||||
|
||||
public static final int OBEX_AUTH_REALM_CHARSET_UNICODE = 0xFF;
|
||||
|
||||
/**
|
||||
* Updates the HeaderSet with the headers received in the byte array
|
||||
* provided. Invalid headers are ignored.
|
||||
@@ -153,37 +197,25 @@ public final class ObexHelper {
|
||||
value.length - 1, "ISO8859_1"));
|
||||
}
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
throw new RuntimeException("ISO8859_1 is not supported"
|
||||
+ e.getMessage());
|
||||
throw e;
|
||||
}
|
||||
break;
|
||||
|
||||
// This is the constant for the authentication challenge header
|
||||
// This header does not have a constant defined in the Java
|
||||
// OBEX API
|
||||
case 0x4D:
|
||||
headerImpl.authChall = new byte[length];
|
||||
System.arraycopy(headerArray, index, headerImpl.authChall, 0,
|
||||
case HeaderSet.AUTH_CHALLENGE:
|
||||
headerImpl.mAuthChall = new byte[length];
|
||||
System.arraycopy(headerArray, index, headerImpl.mAuthChall, 0,
|
||||
length);
|
||||
break;
|
||||
|
||||
// This is the constant for the authentication response header
|
||||
// This header does not have a constant defined in the Java
|
||||
// OBEX API
|
||||
case 0x4E:
|
||||
headerImpl.authResp = new byte[length];
|
||||
System
|
||||
.arraycopy(headerArray, index, headerImpl.authResp, 0,
|
||||
length);
|
||||
case HeaderSet.AUTH_RESPONSE:
|
||||
headerImpl.mAuthResp = new byte[length];
|
||||
System.arraycopy(headerArray, index, headerImpl.mAuthResp, 0,
|
||||
length);
|
||||
break;
|
||||
|
||||
/*
|
||||
* These two case statements are for the body (0x48)
|
||||
* and end of body (0x49) headers.
|
||||
*/
|
||||
case 0x48:
|
||||
case HeaderSet.BODY:
|
||||
/* Fall Through */
|
||||
case 0x49:
|
||||
case HeaderSet.END_OF_BODY:
|
||||
body = new byte[length + 1];
|
||||
body[0] = (byte)headerID;
|
||||
System.arraycopy(headerArray, index, body, 1, length);
|
||||
@@ -211,24 +243,16 @@ public final class ObexHelper {
|
||||
.substring(13, 15)));
|
||||
headerImpl.setHeader(HeaderSet.TIME_ISO_8601, temp);
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
throw new RuntimeException("ISO8859_1 is not supported"
|
||||
+ e.getMessage());
|
||||
} catch (Exception e) {
|
||||
throw new IOException(
|
||||
"Time Header does not follow ISO 8601 standard");
|
||||
throw e;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
try {
|
||||
if ((headerID & 0xC0) == 0x00) {
|
||||
headerImpl.setHeader(headerID, ObexHelper.convertToUnicode(
|
||||
value, true));
|
||||
} else {
|
||||
headerImpl.setHeader(headerID, value);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
// Not a valid header so ignore
|
||||
if ((headerID & 0xC0) == 0x00) {
|
||||
headerImpl.setHeader(headerID, ObexHelper.convertToUnicode(
|
||||
value, true));
|
||||
} else {
|
||||
headerImpl.setHeader(headerID, value);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -262,9 +286,9 @@ public final class ObexHelper {
|
||||
if (headerID != HeaderSet.TIME_4_BYTE) {
|
||||
// Determine if it is a connection ID. These
|
||||
// need to be handled differently
|
||||
if (headerID == 0xCB) {
|
||||
headerImpl.connectionID = new byte[4];
|
||||
System.arraycopy(value, 0, headerImpl.connectionID, 0, 4);
|
||||
if (headerID == HeaderSet.CONNECTION_ID) {
|
||||
headerImpl.mConnectionID = new byte[4];
|
||||
System.arraycopy(value, 0, headerImpl.mConnectionID, 0, 4);
|
||||
} else {
|
||||
headerImpl.setHeader(headerID, Long
|
||||
.valueOf(convertToLong(value)));
|
||||
@@ -328,10 +352,10 @@ public final class ObexHelper {
|
||||
* Determine if there is a connection ID to send. If there is,
|
||||
* then it should be the first header in the packet.
|
||||
*/
|
||||
if ((headImpl.connectionID != null) && (headImpl.getHeader(HeaderSet.TARGET) == null)) {
|
||||
if ((headImpl.mConnectionID != null) && (headImpl.getHeader(HeaderSet.TARGET) == null)) {
|
||||
|
||||
out.write((byte)0xCB);
|
||||
out.write(headImpl.connectionID);
|
||||
out.write((byte)HeaderSet.CONNECTION_ID);
|
||||
out.write(headImpl.mConnectionID);
|
||||
}
|
||||
|
||||
// Count Header
|
||||
@@ -351,8 +375,8 @@ public final class ObexHelper {
|
||||
out.write((byte)HeaderSet.NAME);
|
||||
value = ObexHelper.convertToUnicodeByteArray(stringHeader);
|
||||
length = value.length + 3;
|
||||
lengthArray[0] = (byte)(255 & (length >> 8));
|
||||
lengthArray[1] = (byte)(255 & length);
|
||||
lengthArray[0] = (byte)(0xFF & (length >> 8));
|
||||
lengthArray[1] = (byte)(0xFF & length);
|
||||
out.write(lengthArray);
|
||||
out.write(value);
|
||||
if (nullOut) {
|
||||
@@ -367,7 +391,7 @@ public final class ObexHelper {
|
||||
try {
|
||||
value = stringHeader.getBytes("ISO8859_1");
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
throw new RuntimeException("Unsupported Encoding Scheme: " + e.getMessage());
|
||||
throw e;
|
||||
}
|
||||
|
||||
length = value.length + 4;
|
||||
@@ -440,7 +464,7 @@ public final class ObexHelper {
|
||||
try {
|
||||
value = buffer.toString().getBytes("ISO8859_1");
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
throw new RuntimeException("UnsupportedEncodingException: " + e.getMessage());
|
||||
throw e;
|
||||
}
|
||||
|
||||
length = value.length + 3;
|
||||
@@ -612,28 +636,28 @@ public final class ObexHelper {
|
||||
}
|
||||
|
||||
// Add the authentication challenge header
|
||||
if (headImpl.authChall != null) {
|
||||
out.write((byte)0x4D);
|
||||
length = headImpl.authChall.length + 3;
|
||||
if (headImpl.mAuthChall != null) {
|
||||
out.write((byte)HeaderSet.AUTH_CHALLENGE);
|
||||
length = headImpl.mAuthChall.length + 3;
|
||||
lengthArray[0] = (byte)(255 & (length >> 8));
|
||||
lengthArray[1] = (byte)(255 & length);
|
||||
out.write(lengthArray);
|
||||
out.write(headImpl.authChall);
|
||||
out.write(headImpl.mAuthChall);
|
||||
if (nullOut) {
|
||||
headImpl.authChall = null;
|
||||
headImpl.mAuthChall = null;
|
||||
}
|
||||
}
|
||||
|
||||
// Add the authentication response header
|
||||
if (headImpl.authResp != null) {
|
||||
out.write((byte)0x4E);
|
||||
length = headImpl.authResp.length + 3;
|
||||
if (headImpl.mAuthResp != null) {
|
||||
out.write((byte)HeaderSet.AUTH_RESPONSE);
|
||||
length = headImpl.mAuthResp.length + 3;
|
||||
lengthArray[0] = (byte)(255 & (length >> 8));
|
||||
lengthArray[1] = (byte)(255 & length);
|
||||
out.write(lengthArray);
|
||||
out.write(headImpl.authResp);
|
||||
out.write(headImpl.mAuthResp);
|
||||
if (nullOut) {
|
||||
headImpl.authResp = null;
|
||||
headImpl.mAuthResp = null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -47,8 +47,180 @@ import java.io.IOException;
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public interface ObexSession {
|
||||
public class ObexSession {
|
||||
|
||||
public void close() throws IOException;
|
||||
protected Authenticator mAuthenticator;
|
||||
|
||||
protected byte[] mChallengeDigest;
|
||||
|
||||
/**
|
||||
* Called when the server received an authentication challenge header. This
|
||||
* will cause the authenticator to handle the authentication challenge.
|
||||
*
|
||||
* @param header
|
||||
* the header with the authentication challenge
|
||||
*
|
||||
* @return <code>true</code> if the last request should be resent;
|
||||
* <code>false</code> if the last request should not be resent
|
||||
* @throws IOException
|
||||
*/
|
||||
public boolean handleAuthChall(HeaderSet header) throws IOException {
|
||||
if (mAuthenticator == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* An authentication challenge is made up of one required and two
|
||||
* optional tag length value triplets. The tag 0x00 is required to be in
|
||||
* the authentication challenge and it represents the challenge digest
|
||||
* that was received. The tag 0x01 is the options tag. This tag tracks
|
||||
* if user ID is required and if full access will be granted. The tag
|
||||
* 0x02 is the realm, which provides a description of which user name
|
||||
* and password to use.
|
||||
*/
|
||||
byte[] challenge = ObexHelper.getTagValue((byte)0x00, header.mAuthChall);
|
||||
byte[] option = ObexHelper.getTagValue((byte)0x01, header.mAuthChall);
|
||||
byte[] description = ObexHelper.getTagValue((byte)0x02, header.mAuthChall);
|
||||
|
||||
String realm = null;
|
||||
if (description != null) {
|
||||
byte[] realmString = new byte[description.length - 1];
|
||||
System.arraycopy(description, 1, realmString, 0, realmString.length);
|
||||
|
||||
switch (description[0] & 0xFF) {
|
||||
|
||||
case ObexHelper.OBEX_AUTH_REALM_CHARSET_ASCII:
|
||||
// ASCII encoding
|
||||
// Fall through
|
||||
case ObexHelper.OBEX_AUTH_REALM_CHARSET_ISO_8859_1:
|
||||
// ISO-8859-1 encoding
|
||||
try {
|
||||
realm = new String(realmString, "ISO8859_1");
|
||||
} catch (Exception e) {
|
||||
throw new IOException("Unsupported Encoding Scheme");
|
||||
}
|
||||
break;
|
||||
|
||||
case ObexHelper.OBEX_AUTH_REALM_CHARSET_UNICODE:
|
||||
// UNICODE Encoding
|
||||
realm = ObexHelper.convertToUnicode(realmString, false);
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new IOException("Unsupported Encoding Scheme");
|
||||
}
|
||||
}
|
||||
|
||||
boolean isUserIDRequired = false;
|
||||
boolean isFullAccess = true;
|
||||
if (option != null) {
|
||||
if ((option[0] & 0x01) != 0) {
|
||||
isUserIDRequired = true;
|
||||
}
|
||||
|
||||
if ((option[0] & 0x02) != 0) {
|
||||
isFullAccess = false;
|
||||
}
|
||||
}
|
||||
|
||||
PasswordAuthentication result = null;
|
||||
header.mAuthChall = null;
|
||||
|
||||
try {
|
||||
result = mAuthenticator
|
||||
.onAuthenticationChallenge(realm, isUserIDRequired, isFullAccess);
|
||||
} catch (Exception e) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* If no password is provided then we not resent the request
|
||||
*/
|
||||
if (result == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
byte[] password = result.getPassword();
|
||||
if (password == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
byte[] userName = result.getUserName();
|
||||
|
||||
/*
|
||||
* Create the authentication response header. It includes 1 required and
|
||||
* 2 option tag length value triples. The required triple has a tag of
|
||||
* 0x00 and is the response digest. The first optional tag is 0x01 and
|
||||
* represents the user ID. If no user ID is provided, then no user ID
|
||||
* will be sent. The second optional tag is 0x02 and is the challenge
|
||||
* that was received. This will always be sent
|
||||
*/
|
||||
if (userName != null) {
|
||||
header.mAuthResp = new byte[38 + userName.length];
|
||||
header.mAuthResp[36] = (byte)0x01;
|
||||
header.mAuthResp[37] = (byte)userName.length;
|
||||
System.arraycopy(userName, 0, header.mAuthResp, 38, userName.length);
|
||||
} else {
|
||||
header.mAuthResp = new byte[36];
|
||||
}
|
||||
|
||||
// Create the secret String
|
||||
byte[] digest = new byte[challenge.length + password.length + 1];
|
||||
System.arraycopy(challenge, 0, digest, 0, challenge.length);
|
||||
// Insert colon between challenge and password
|
||||
digest[challenge.length] = (byte)0x3A;
|
||||
System.arraycopy(password, 0, digest, challenge.length + 1, password.length);
|
||||
|
||||
// Add the Response Digest
|
||||
header.mAuthResp[0] = (byte)0x00;
|
||||
header.mAuthResp[1] = (byte)0x10;
|
||||
|
||||
System.arraycopy(ObexHelper.computeMd5Hash(digest), 0, header.mAuthResp, 2, 16);
|
||||
|
||||
// Add the challenge
|
||||
header.mAuthResp[18] = (byte)0x02;
|
||||
header.mAuthResp[19] = (byte)0x10;
|
||||
System.arraycopy(challenge, 0, header.mAuthResp, 20, 16);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the server received an authentication response header. This
|
||||
* will cause the authenticator to handle the authentication response.
|
||||
*
|
||||
* @param authResp
|
||||
* the authentication response
|
||||
*
|
||||
* @return <code>true</code> if the response passed; <code>false</code> if
|
||||
* the response failed
|
||||
*/
|
||||
public boolean handleAuthResp(byte[] authResp) {
|
||||
if (mAuthenticator == null) {
|
||||
return false;
|
||||
}
|
||||
// get the correct password from the application
|
||||
byte[] correctPassword = mAuthenticator.onAuthenticationResponse(ObexHelper.getTagValue(
|
||||
(byte)0x01, authResp));
|
||||
if (correctPassword == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
byte[] temp = new byte[correctPassword.length + 16];
|
||||
|
||||
System.arraycopy(mChallengeDigest, 0, temp, 0, 16);
|
||||
System.arraycopy(correctPassword, 0, temp, 16, correctPassword.length);
|
||||
|
||||
byte[] correctResponse = ObexHelper.computeMd5Hash(temp);
|
||||
byte[] actualResponse = ObexHelper.getTagValue((byte)0x00, authResp);
|
||||
|
||||
// compare the MD5 hash array .
|
||||
for (int i = 0; i < 16; i++) {
|
||||
if (correctResponse[i] != actualResponse[i]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -137,7 +137,7 @@ public interface Operation {
|
||||
* @throws IOException if the transaction has already ended or if an
|
||||
* OBEX server calls this method
|
||||
*/
|
||||
public void abort() throws IOException;
|
||||
void abort() throws IOException;
|
||||
|
||||
/**
|
||||
* Returns the headers that have been received during the operation.
|
||||
@@ -148,7 +148,7 @@ public interface Operation {
|
||||
*
|
||||
* @throws IOException if this <code>Operation</code> has been closed
|
||||
*/
|
||||
public HeaderSet getReceivedHeaders() throws IOException;
|
||||
HeaderSet getReceivedHeader() throws IOException;
|
||||
|
||||
/**
|
||||
* Specifies the headers that should be sent in the next OBEX message that
|
||||
@@ -165,7 +165,7 @@ public interface Operation {
|
||||
*
|
||||
* @throws NullPointerException if <code>headers</code> if <code>null</code>
|
||||
*/
|
||||
public void sendHeaders(HeaderSet headers) throws IOException;
|
||||
void sendHeaders(HeaderSet headers) throws IOException;
|
||||
|
||||
/**
|
||||
* Returns the response code received from the server. Response codes
|
||||
@@ -178,23 +178,23 @@ public interface Operation {
|
||||
* @throws IOException if an error occurred in the transport layer during
|
||||
* the transaction; if this object was created by an OBEX server
|
||||
*/
|
||||
public int getResponseCode() throws IOException;
|
||||
int getResponseCode() throws IOException;
|
||||
|
||||
public String getEncoding();
|
||||
String getEncoding();
|
||||
|
||||
public long getLength();
|
||||
long getLength();
|
||||
|
||||
public String getType();
|
||||
String getType();
|
||||
|
||||
public InputStream openInputStream() throws IOException;
|
||||
InputStream openInputStream() throws IOException;
|
||||
|
||||
public DataInputStream openDataInputStream() throws IOException;
|
||||
DataInputStream openDataInputStream() throws IOException;
|
||||
|
||||
public OutputStream openOutputStream() throws IOException;
|
||||
OutputStream openOutputStream() throws IOException;
|
||||
|
||||
public DataOutputStream openDataOutputStream() throws IOException;
|
||||
DataOutputStream openDataOutputStream() throws IOException;
|
||||
|
||||
public void close() throws IOException;
|
||||
void close() throws IOException;
|
||||
|
||||
public int getMaxPacketSize();
|
||||
int getMaxPacketSize();
|
||||
}
|
||||
|
||||
@@ -37,11 +37,11 @@ package javax.obex;
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public class PasswordAuthentication {
|
||||
public final class PasswordAuthentication {
|
||||
|
||||
private byte[] userName;
|
||||
private byte[] mUserName;
|
||||
|
||||
private byte[] password;
|
||||
private final byte[] mPassword;
|
||||
|
||||
/**
|
||||
* Creates a new <code>PasswordAuthentication</code> with the user name
|
||||
@@ -51,17 +51,17 @@ public class PasswordAuthentication {
|
||||
*
|
||||
* @param password the password to include in the response
|
||||
*
|
||||
* @exception NullPointerException if <code>password</code> is
|
||||
* @throws NullPointerException if <code>password</code> is
|
||||
* <code>null</code>
|
||||
*/
|
||||
public PasswordAuthentication(byte[] userName, byte[] password) {
|
||||
public PasswordAuthentication(final byte[] userName, final byte[] password) {
|
||||
if (userName != null) {
|
||||
this.userName = new byte[userName.length];
|
||||
System.arraycopy(userName, 0, this.userName, 0, userName.length);
|
||||
mUserName = new byte[userName.length];
|
||||
System.arraycopy(userName, 0, mUserName, 0, userName.length);
|
||||
}
|
||||
|
||||
this.password = new byte[password.length];
|
||||
System.arraycopy(password, 0, this.password, 0, password.length);
|
||||
mPassword = new byte[password.length];
|
||||
System.arraycopy(password, 0, mPassword, 0, password.length);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -71,7 +71,7 @@ public class PasswordAuthentication {
|
||||
* @return the user name
|
||||
*/
|
||||
public byte[] getUserName() {
|
||||
return this.userName;
|
||||
return mUserName;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -80,6 +80,6 @@ public class PasswordAuthentication {
|
||||
* @return the password
|
||||
*/
|
||||
public byte[] getPassword() {
|
||||
return this.password;
|
||||
return mPassword;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,23 +39,17 @@ import java.io.IOException;
|
||||
* This object provides an input stream to the Operation objects used in this
|
||||
* package.
|
||||
*
|
||||
* TODO: Include the other read() methods defined in InputStream.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public class PrivateInputStream extends InputStream {
|
||||
public final class PrivateInputStream extends InputStream {
|
||||
|
||||
private BaseStream parent;
|
||||
private BaseStream mParent;
|
||||
|
||||
private byte[] data;
|
||||
private byte[] mData;
|
||||
|
||||
private int index;
|
||||
private int mIndex;
|
||||
|
||||
private boolean isOpen;
|
||||
|
||||
public PrivateInputStream() {
|
||||
|
||||
}
|
||||
private boolean mOpen;
|
||||
|
||||
/**
|
||||
* Creates an input stream for the <code>Operation</code> to read from
|
||||
@@ -63,10 +57,10 @@ public class PrivateInputStream extends InputStream {
|
||||
* @param p the connection this input stream is for
|
||||
*/
|
||||
public PrivateInputStream(BaseStream p) {
|
||||
parent = p;
|
||||
data = new byte[0];
|
||||
index = 0;
|
||||
isOpen = true;
|
||||
mParent = p;
|
||||
mData = new byte[0];
|
||||
mIndex = 0;
|
||||
mOpen = true;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -83,7 +77,7 @@ public class PrivateInputStream extends InputStream {
|
||||
@Override
|
||||
public synchronized int available() throws IOException {
|
||||
ensureOpen();
|
||||
return data.length - index;
|
||||
return mData.length - mIndex;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -101,12 +95,12 @@ public class PrivateInputStream extends InputStream {
|
||||
@Override
|
||||
public synchronized int read() throws IOException {
|
||||
ensureOpen();
|
||||
while (data.length == index) {
|
||||
if (!parent.continueOperation(true, true)) {
|
||||
while (mData.length == mIndex) {
|
||||
if (!mParent.continueOperation(true, true)) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return (data[index++] & 0xFF);
|
||||
return (mData[mIndex++] & 0xFF);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -118,33 +112,33 @@ public class PrivateInputStream extends InputStream {
|
||||
public synchronized int read(byte[] b, int offset, int length) throws IOException {
|
||||
|
||||
if (b == null) {
|
||||
throw new NullPointerException("buffer is null");
|
||||
throw new IOException("buffer is null");
|
||||
}
|
||||
if ((offset | length) < 0 || length > b.length - offset) {
|
||||
throw new ArrayIndexOutOfBoundsException("index outof bound");
|
||||
}
|
||||
ensureOpen();
|
||||
|
||||
int currentDataLength = data.length - index;
|
||||
int currentDataLength = mData.length - mIndex;
|
||||
int remainReadLength = length;
|
||||
int offset1 = offset;
|
||||
int result = 0;
|
||||
|
||||
while (currentDataLength <= remainReadLength) {
|
||||
System.arraycopy(data, index, b, offset1, currentDataLength);
|
||||
index += currentDataLength;
|
||||
System.arraycopy(mData, mIndex, b, offset1, currentDataLength);
|
||||
mIndex += currentDataLength;
|
||||
offset1 += currentDataLength;
|
||||
result += currentDataLength;
|
||||
remainReadLength -= currentDataLength;
|
||||
|
||||
if (!parent.continueOperation(true, true)) {
|
||||
if (!mParent.continueOperation(true, true)) {
|
||||
return result == 0 ? -1 : result;
|
||||
}
|
||||
currentDataLength = data.length - index;
|
||||
currentDataLength = mData.length - mIndex;
|
||||
}
|
||||
if (remainReadLength > 0) {
|
||||
System.arraycopy(data, index, b, offset1, remainReadLength);
|
||||
index += remainReadLength;
|
||||
System.arraycopy(mData, mIndex, b, offset1, remainReadLength);
|
||||
mIndex += remainReadLength;
|
||||
result += remainReadLength;
|
||||
}
|
||||
return result;
|
||||
@@ -160,14 +154,14 @@ public class PrivateInputStream extends InputStream {
|
||||
*/
|
||||
public synchronized void writeBytes(byte[] body, int start) {
|
||||
|
||||
int length = (body.length - start) + (data.length - index);
|
||||
int length = (body.length - start) + (mData.length - mIndex);
|
||||
byte[] temp = new byte[length];
|
||||
|
||||
System.arraycopy(data, index, temp, 0, data.length - index);
|
||||
System.arraycopy(body, start, temp, data.length - index, body.length - start);
|
||||
System.arraycopy(mData, mIndex, temp, 0, mData.length - mIndex);
|
||||
System.arraycopy(body, start, temp, mData.length - mIndex, body.length - start);
|
||||
|
||||
data = temp;
|
||||
index = 0;
|
||||
mData = temp;
|
||||
mIndex = 0;
|
||||
notifyAll();
|
||||
}
|
||||
|
||||
@@ -177,8 +171,8 @@ public class PrivateInputStream extends InputStream {
|
||||
* @throws IOException if the stream is not open
|
||||
*/
|
||||
private void ensureOpen() throws IOException {
|
||||
parent.ensureOpen();
|
||||
if (!isOpen) {
|
||||
mParent.ensureOpen();
|
||||
if (!mOpen) {
|
||||
throw new IOException("Input stream is closed");
|
||||
}
|
||||
}
|
||||
@@ -191,7 +185,7 @@ public class PrivateInputStream extends InputStream {
|
||||
*/
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
isOpen = false;
|
||||
parent.streamClosed(true);
|
||||
mOpen = false;
|
||||
mParent.streamClosed(true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,15 +42,15 @@ import java.io.ByteArrayOutputStream;
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
class PrivateOutputStream extends OutputStream {
|
||||
public final class PrivateOutputStream extends OutputStream {
|
||||
|
||||
private BaseStream parent;
|
||||
private BaseStream mParent;
|
||||
|
||||
private ByteArrayOutputStream output;
|
||||
private ByteArrayOutputStream mArray;
|
||||
|
||||
private boolean isClosed;
|
||||
private boolean mOpen;
|
||||
|
||||
private int maxPacketSize;
|
||||
private int mMaxPacketSize;
|
||||
|
||||
/**
|
||||
* Creates an empty <code>PrivateOutputStream</code> to write to.
|
||||
@@ -58,9 +58,9 @@ class PrivateOutputStream extends OutputStream {
|
||||
* @param p the connection that this stream runs over
|
||||
*/
|
||||
public PrivateOutputStream(BaseStream p, int maxSize) {
|
||||
parent = p;
|
||||
output = new ByteArrayOutputStream();
|
||||
maxPacketSize = maxSize;
|
||||
mParent = p;
|
||||
mArray = new ByteArrayOutputStream();
|
||||
mMaxPacketSize = maxSize;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -68,8 +68,8 @@ class PrivateOutputStream extends OutputStream {
|
||||
*
|
||||
* @return the number of bytes written to the output stream
|
||||
*/
|
||||
protected int size() {
|
||||
return output.size();
|
||||
public int size() {
|
||||
return mArray.size();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -85,10 +85,10 @@ class PrivateOutputStream extends OutputStream {
|
||||
@Override
|
||||
public synchronized void write(int b) throws IOException {
|
||||
ensureOpen();
|
||||
parent.ensureNotDone();
|
||||
output.write(b);
|
||||
if (output.size() == maxPacketSize) {
|
||||
parent.continueOperation(true, false);
|
||||
mParent.ensureNotDone();
|
||||
mArray.write(b);
|
||||
if (mArray.size() == mMaxPacketSize) {
|
||||
mParent.continueOperation(true, false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -103,44 +103,29 @@ class PrivateOutputStream extends OutputStream {
|
||||
int remainLength = count;
|
||||
|
||||
if (buffer == null) {
|
||||
throw new NullPointerException("buffer is null");
|
||||
throw new IOException("buffer is null");
|
||||
}
|
||||
if ((offset | count) < 0 || count > buffer.length - offset) {
|
||||
throw new IndexOutOfBoundsException("index outof bound");
|
||||
}
|
||||
|
||||
ensureOpen();
|
||||
parent.ensureNotDone();
|
||||
if (count < maxPacketSize) {
|
||||
output.write(buffer, offset, count);
|
||||
mParent.ensureNotDone();
|
||||
if (count < mMaxPacketSize) {
|
||||
mArray.write(buffer, offset, count);
|
||||
} else {
|
||||
while (remainLength >= maxPacketSize) {
|
||||
output.write(buffer, offset1, maxPacketSize);
|
||||
offset1 += maxPacketSize;
|
||||
while (remainLength >= mMaxPacketSize) {
|
||||
mArray.write(buffer, offset1, mMaxPacketSize);
|
||||
offset1 += mMaxPacketSize;
|
||||
remainLength = count - offset1;
|
||||
parent.continueOperation(true, false);
|
||||
mParent.continueOperation(true, false);
|
||||
}
|
||||
if (remainLength > 0) {
|
||||
output.write(buffer, offset1, remainLength);
|
||||
mArray.write(buffer, offset1, remainLength);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads the bytes that have been written to this stream.
|
||||
*
|
||||
* @return the byte array that is written
|
||||
*/
|
||||
protected synchronized byte[] readBytes() {
|
||||
if (output.size() > 0) {
|
||||
byte[] result = output.toByteArray();
|
||||
output.reset();
|
||||
return result;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads the bytes that have been written to this stream.
|
||||
*
|
||||
@@ -148,14 +133,14 @@ class PrivateOutputStream extends OutputStream {
|
||||
*
|
||||
* @return the byte array that is written
|
||||
*/
|
||||
protected synchronized byte[] readBytes(int size) {
|
||||
if (output.size() > 0) {
|
||||
byte[] temp = output.toByteArray();
|
||||
output.reset();
|
||||
public synchronized byte[] readBytes(int size) {
|
||||
if (mArray.size() > 0) {
|
||||
byte[] temp = mArray.toByteArray();
|
||||
mArray.reset();
|
||||
byte[] result = new byte[size];
|
||||
System.arraycopy(temp, 0, result, 0, size);
|
||||
if (temp.length != size) {
|
||||
output.write(temp, size, temp.length - size);
|
||||
mArray.write(temp, size, temp.length - size);
|
||||
}
|
||||
return result;
|
||||
} else {
|
||||
@@ -169,8 +154,8 @@ class PrivateOutputStream extends OutputStream {
|
||||
* @throws IOException if the stream is not open
|
||||
*/
|
||||
private void ensureOpen() throws IOException {
|
||||
parent.ensureOpen();
|
||||
if (isClosed) {
|
||||
mParent.ensureOpen();
|
||||
if (!mOpen) {
|
||||
throw new IOException("Output stream is closed");
|
||||
}
|
||||
}
|
||||
@@ -183,8 +168,8 @@ class PrivateOutputStream extends OutputStream {
|
||||
*/
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
isClosed = true;
|
||||
parent.streamClosed(false);
|
||||
mOpen = false;
|
||||
mParent.streamClosed(false);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -193,7 +178,7 @@ class PrivateOutputStream extends OutputStream {
|
||||
* @return <code>true</code> if the connection is closed;
|
||||
* <code>false</code> if the connection is open
|
||||
*/
|
||||
protected boolean isClosed() {
|
||||
return isClosed;
|
||||
public boolean isClosed() {
|
||||
return !mOpen;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,11 +38,8 @@ package javax.obex;
|
||||
* <P>
|
||||
* <STRONG>IMPORTANT NOTE</STRONG>
|
||||
* <P>
|
||||
* It is important to note that these values are different then those defined
|
||||
* in <code>javax.microedition.io.HttpConnection</code>. The values in this
|
||||
* interface represent the values defined in the IrOBEX specification. The
|
||||
* values in <code>javax.microedition.io.HttpConnection</code> represent values
|
||||
* defined in the HTTP specification.
|
||||
* The values in this interface represent the values defined in the IrOBEX
|
||||
* specification, which is different with the HTTP specification.
|
||||
* <P>
|
||||
* <code>OBEX_DATABASE_FULL</code> and <code>OBEX_DATABASE_LOCKED</code> require
|
||||
* further description since they are not defined in HTTP. The server will send
|
||||
@@ -54,7 +51,14 @@ package javax.obex;
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public class ResponseCodes {
|
||||
public final class ResponseCodes {
|
||||
|
||||
/**
|
||||
* Defines the OBEX CONTINUE response code.
|
||||
* <P>
|
||||
* The value of <code>OBEX_HTTP_CONTINUE</code> is 0x90 (144).
|
||||
*/
|
||||
public static final int OBEX_HTTP_CONTINUE = 0x90;
|
||||
|
||||
/**
|
||||
* Defines the OBEX SUCCESS response code.
|
||||
@@ -318,5 +322,6 @@ public class ResponseCodes {
|
||||
/**
|
||||
* Constructor does nothing.
|
||||
*/
|
||||
private ResponseCodes() {}
|
||||
private ResponseCodes() {
|
||||
}
|
||||
}
|
||||
|
||||
@@ -48,7 +48,7 @@ import java.io.ByteArrayOutputStream;
|
||||
* additional OBEX packet. 0x82 is a PUT request that says that request is
|
||||
* complete. In this case, the server can begin sending the response. The
|
||||
* 0x03 is a GET request that signals that the request is not finished. When
|
||||
* the server receives a 0x83, the client is signalling the server that it is
|
||||
* the server receives a 0x83, the client is signaling the server that it is
|
||||
* done with its request.
|
||||
*
|
||||
* TODO: Extend the ClientOperation and reuse the methods defined
|
||||
@@ -56,52 +56,44 @@ import java.io.ByteArrayOutputStream;
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public class ServerOperation implements Operation, BaseStream {
|
||||
public final class ServerOperation implements Operation, BaseStream {
|
||||
|
||||
private InputStream socketInput;
|
||||
public boolean isAborted;
|
||||
|
||||
private ServerSession parent;
|
||||
public HeaderSet requestHeader;
|
||||
|
||||
private int maxPacketLength;
|
||||
public HeaderSet replyHeader;
|
||||
|
||||
private int responseSize;
|
||||
public boolean finalBitSet;
|
||||
|
||||
private boolean isClosed;
|
||||
private InputStream mInput;
|
||||
|
||||
boolean finalBitSet;
|
||||
private ServerSession mParent;
|
||||
|
||||
// This variable defines when the end of body
|
||||
// header has been received. When this header
|
||||
// is received, no further body data will be
|
||||
// received from the client
|
||||
private boolean endOfBody;
|
||||
private int mMaxPacketLength;
|
||||
|
||||
private boolean isGet;
|
||||
private int mResponseSize;
|
||||
|
||||
boolean isAborted;
|
||||
private boolean mClosed;
|
||||
|
||||
HeaderSet requestHeaders;
|
||||
private boolean mGetOperation;
|
||||
|
||||
HeaderSet replyHeaders;
|
||||
private PrivateInputStream mPrivateInput;
|
||||
|
||||
PrivateInputStream privateInput;
|
||||
private PrivateOutputStream mPrivateOutput;
|
||||
|
||||
private PrivateOutputStream privateOutput;
|
||||
private boolean mPrivateOutputOpen;
|
||||
|
||||
private String exceptionString;
|
||||
private String mExceptionString;
|
||||
|
||||
private ServerRequestHandler listener;
|
||||
private ServerRequestHandler mListener;
|
||||
|
||||
private boolean outputStreamOpened;
|
||||
private boolean mRequestFinished;
|
||||
|
||||
private boolean requestFinished;
|
||||
|
||||
private static final int BASE_PACKET_LENGTH = 3;
|
||||
|
||||
private boolean isHasBody;
|
||||
private boolean mHasBody;
|
||||
|
||||
/**
|
||||
* Creates new PutServerOperation
|
||||
* Creates new ServerOperation
|
||||
*
|
||||
* @param p the parent that created this object
|
||||
*
|
||||
@@ -121,19 +113,18 @@ public class ServerOperation implements Operation, BaseStream {
|
||||
ServerRequestHandler listen) throws IOException {
|
||||
|
||||
isAborted = false;
|
||||
parent = p;
|
||||
socketInput = in;
|
||||
maxPacketLength = maxSize;
|
||||
isClosed = false;
|
||||
requestHeaders = new HeaderSet();
|
||||
replyHeaders = new HeaderSet();
|
||||
privateInput = new PrivateInputStream(this);
|
||||
endOfBody = false;
|
||||
responseSize = 3;
|
||||
listener = listen;
|
||||
requestFinished = false;
|
||||
outputStreamOpened = false;
|
||||
isHasBody = false;
|
||||
mParent = p;
|
||||
mInput = in;
|
||||
mMaxPacketLength = maxSize;
|
||||
mClosed = false;
|
||||
requestHeader = new HeaderSet();
|
||||
replyHeader = new HeaderSet();
|
||||
mPrivateInput = new PrivateInputStream(this);
|
||||
mResponseSize = 3;
|
||||
mListener = listen;
|
||||
mRequestFinished = false;
|
||||
mPrivateOutputOpen = false;
|
||||
mHasBody = false;
|
||||
int bytesReceived;
|
||||
|
||||
/*
|
||||
@@ -143,12 +134,12 @@ public class ServerOperation implements Operation, BaseStream {
|
||||
/*
|
||||
* It is a PUT request.
|
||||
*/
|
||||
isGet = false;
|
||||
mGetOperation = false;
|
||||
} else {
|
||||
/*
|
||||
* It is a GET request.
|
||||
*/
|
||||
isGet = true;
|
||||
mGetOperation = true;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -158,7 +149,7 @@ public class ServerOperation implements Operation, BaseStream {
|
||||
finalBitSet = false;
|
||||
} else {
|
||||
finalBitSet = true;
|
||||
requestFinished = true;
|
||||
mRequestFinished = true;
|
||||
}
|
||||
|
||||
int length = in.read();
|
||||
@@ -168,7 +159,7 @@ public class ServerOperation implements Operation, BaseStream {
|
||||
* Determine if the packet length is larger than this device can receive
|
||||
*/
|
||||
if (length > ObexHelper.MAX_PACKET_SIZE_INT) {
|
||||
parent.sendResponse(ResponseCodes.OBEX_HTTP_REQ_TOO_LARGE, null);
|
||||
mParent.sendResponse(ResponseCodes.OBEX_HTTP_REQ_TOO_LARGE, null);
|
||||
throw new IOException("Packet received was too large");
|
||||
}
|
||||
|
||||
@@ -183,81 +174,69 @@ public class ServerOperation implements Operation, BaseStream {
|
||||
bytesReceived += in.read(data, bytesReceived, data.length - bytesReceived);
|
||||
}
|
||||
|
||||
byte[] body = ObexHelper.updateHeaderSet(requestHeaders, data);
|
||||
byte[] body = ObexHelper.updateHeaderSet(requestHeader, data);
|
||||
|
||||
if (body != null) {
|
||||
isHasBody = true;
|
||||
mHasBody = true;
|
||||
}
|
||||
|
||||
if (requestHeaders.connectionID != null) {
|
||||
listener.setConnectionID(ObexHelper.convertToLong(requestHeaders.connectionID));
|
||||
if (requestHeader.mConnectionID != null) {
|
||||
mListener.setConnectionId(ObexHelper.convertToLong(requestHeader.mConnectionID));
|
||||
} else {
|
||||
listener.setConnectionID(0);
|
||||
mListener.setConnectionId(0);
|
||||
}
|
||||
|
||||
if (requestHeaders.authResp != null) {
|
||||
if (!parent.handleAuthResp(requestHeaders.authResp)) {
|
||||
exceptionString = "Authentication Failed";
|
||||
parent.sendResponse(ResponseCodes.OBEX_HTTP_UNAUTHORIZED, null);
|
||||
isClosed = true;
|
||||
requestHeaders.authResp = null;
|
||||
if (requestHeader.mAuthResp != null) {
|
||||
if (!mParent.handleAuthResp(requestHeader.mAuthResp)) {
|
||||
mExceptionString = "Authentication Failed";
|
||||
mParent.sendResponse(ResponseCodes.OBEX_HTTP_UNAUTHORIZED, null);
|
||||
mClosed = true;
|
||||
requestHeader.mAuthResp = null;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (requestHeaders.authChall != null) {
|
||||
parent.handleAuthChall(requestHeaders);
|
||||
if (requestHeader.mAuthChall != null) {
|
||||
mParent.handleAuthChall(requestHeader);
|
||||
// send the authResp to the client
|
||||
replyHeaders.authResp = new byte[requestHeaders.authResp.length];
|
||||
System.arraycopy(requestHeaders.authResp, 0, replyHeaders.authResp, 0,
|
||||
replyHeaders.authResp.length);
|
||||
requestHeaders.authResp = null;
|
||||
requestHeaders.authChall = null;
|
||||
replyHeader.mAuthResp = new byte[requestHeader.mAuthResp.length];
|
||||
System.arraycopy(requestHeader.mAuthResp, 0, replyHeader.mAuthResp, 0,
|
||||
replyHeader.mAuthResp.length);
|
||||
requestHeader.mAuthResp = null;
|
||||
requestHeader.mAuthChall = null;
|
||||
|
||||
}
|
||||
|
||||
if (body != null) {
|
||||
/*
|
||||
* 0x49 is the end of body header. This signifies that no more
|
||||
* body data will be sent from the client
|
||||
*/
|
||||
if (body[0] == 0x49) {
|
||||
endOfBody = true;
|
||||
}
|
||||
//privateInput.writeBytes(body, body.length);
|
||||
//byte [] body_tmp = new byte[body.length-1];
|
||||
//System.arraycopy(body,1,body_tmp,0,body.length-1);
|
||||
//privateInput.writeBytes(body_tmp, body.length-1);
|
||||
privateInput.writeBytes(body, 1);
|
||||
mPrivateInput.writeBytes(body, 1);
|
||||
} else {
|
||||
while ((!isGet) && (!finalBitSet)) {
|
||||
sendReply(ObexHelper.OBEX_HTTP_CONTINUE);
|
||||
if (privateInput.available() > 0) {
|
||||
while ((!mGetOperation) && (!finalBitSet)) {
|
||||
sendReply(ResponseCodes.OBEX_HTTP_CONTINUE);
|
||||
if (mPrivateInput.available() > 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}// if (body != null)
|
||||
}
|
||||
}
|
||||
|
||||
}// if (length > 3)
|
||||
|
||||
while ((!isGet) && (!finalBitSet) && (privateInput.available() == 0)) {
|
||||
sendReply(ObexHelper.OBEX_HTTP_CONTINUE);
|
||||
if (privateInput.available() > 0) {
|
||||
while ((!mGetOperation) && (!finalBitSet) && (mPrivateInput.available() == 0)) {
|
||||
sendReply(ResponseCodes.OBEX_HTTP_CONTINUE);
|
||||
if (mPrivateInput.available() > 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// wait for get request finished !!!!
|
||||
while (isGet && !finalBitSet) {
|
||||
sendReply(ObexHelper.OBEX_HTTP_CONTINUE);
|
||||
while (mGetOperation && !finalBitSet) {
|
||||
sendReply(ResponseCodes.OBEX_HTTP_CONTINUE);
|
||||
}
|
||||
if (finalBitSet && isGet) {
|
||||
requestFinished = true;
|
||||
if (finalBitSet && mGetOperation) {
|
||||
mRequestFinished = true;
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized boolean isValidBody() {
|
||||
return isHasBody;
|
||||
public boolean isValidBody() {
|
||||
return mHasBody;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -268,21 +247,21 @@ public class ServerOperation implements Operation, BaseStream {
|
||||
* operation even if no headers will be sent; if <code>false</code> then
|
||||
* this method will only continue the operation if there are headers to
|
||||
* send
|
||||
* @param isStream if<code>true</code> the stream is input stream or
|
||||
* is outputstream
|
||||
* @param isStream if<code>true</code> the stream is input stream, otherwise
|
||||
* output stream
|
||||
* @return <code>true</code> if the operation was completed;
|
||||
* <code>false</code> if no operation took place
|
||||
*/
|
||||
public synchronized boolean continueOperation(boolean sendEmpty, boolean inStream)
|
||||
throws IOException {
|
||||
if (!isGet) {
|
||||
if (!mGetOperation) {
|
||||
if (!finalBitSet) {
|
||||
if (sendEmpty) {
|
||||
sendReply(ObexHelper.OBEX_HTTP_CONTINUE);
|
||||
sendReply(ResponseCodes.OBEX_HTTP_CONTINUE);
|
||||
return true;
|
||||
} else {
|
||||
if ((responseSize > 3) || (privateOutput.size() > 0)) {
|
||||
sendReply(ObexHelper.OBEX_HTTP_CONTINUE);
|
||||
if ((mResponseSize > 3) || (mPrivateOutput.size() > 0)) {
|
||||
sendReply(ResponseCodes.OBEX_HTTP_CONTINUE);
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
@@ -292,7 +271,7 @@ public class ServerOperation implements Operation, BaseStream {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
sendReply(ObexHelper.OBEX_HTTP_CONTINUE);
|
||||
sendReply(ResponseCodes.OBEX_HTTP_CONTINUE);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -309,52 +288,52 @@ public class ServerOperation implements Operation, BaseStream {
|
||||
*
|
||||
* @throws IOException if an IO error occurs
|
||||
*/
|
||||
protected synchronized boolean sendReply(int type) throws IOException {
|
||||
public synchronized boolean sendReply(int type) throws IOException {
|
||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||
int bytesReceived;
|
||||
|
||||
long id = listener.getConnectionID();
|
||||
long id = mListener.getConnectionId();
|
||||
if (id == -1) {
|
||||
replyHeaders.connectionID = null;
|
||||
replyHeader.mConnectionID = null;
|
||||
} else {
|
||||
replyHeaders.connectionID = ObexHelper.convertToByteArray(id);
|
||||
replyHeader.mConnectionID = ObexHelper.convertToByteArray(id);
|
||||
}
|
||||
|
||||
byte[] headerArray = ObexHelper.createHeader(replyHeaders, true);
|
||||
byte[] headerArray = ObexHelper.createHeader(replyHeader, true);
|
||||
int bodyLength = -1;
|
||||
int orginalBodyLength = -1;
|
||||
|
||||
if (privateOutput != null) {
|
||||
bodyLength = privateOutput.size();
|
||||
if (mPrivateOutput != null) {
|
||||
bodyLength = mPrivateOutput.size();
|
||||
orginalBodyLength = bodyLength;
|
||||
}
|
||||
|
||||
if ((BASE_PACKET_LENGTH + headerArray.length) > maxPacketLength) {
|
||||
if ((ObexHelper.BASE_PACKET_LENGTH + headerArray.length) > mMaxPacketLength) {
|
||||
|
||||
int end = 0;
|
||||
int start = 0;
|
||||
|
||||
while (end != headerArray.length) {
|
||||
end = ObexHelper.findHeaderEnd(headerArray, start, maxPacketLength
|
||||
- BASE_PACKET_LENGTH);
|
||||
end = ObexHelper.findHeaderEnd(headerArray, start, mMaxPacketLength
|
||||
- ObexHelper.BASE_PACKET_LENGTH);
|
||||
if (end == -1) {
|
||||
|
||||
isClosed = true;
|
||||
mClosed = true;
|
||||
|
||||
if (privateInput != null) {
|
||||
privateInput.close();
|
||||
if (mPrivateInput != null) {
|
||||
mPrivateInput.close();
|
||||
}
|
||||
|
||||
if (privateOutput != null) {
|
||||
privateOutput.close();
|
||||
if (mPrivateOutput != null) {
|
||||
mPrivateOutput.close();
|
||||
}
|
||||
parent.sendResponse(ResponseCodes.OBEX_HTTP_INTERNAL_ERROR, null);
|
||||
mParent.sendResponse(ResponseCodes.OBEX_HTTP_INTERNAL_ERROR, null);
|
||||
throw new IOException("OBEX Packet exceeds max packet size");
|
||||
}
|
||||
byte[] sendHeader = new byte[end - start];
|
||||
System.arraycopy(headerArray, start, sendHeader, 0, sendHeader.length);
|
||||
|
||||
parent.sendResponse(type, sendHeader);
|
||||
mParent.sendResponse(type, sendHeader);
|
||||
start = end;
|
||||
}
|
||||
|
||||
@@ -368,48 +347,25 @@ public class ServerOperation implements Operation, BaseStream {
|
||||
out.write(headerArray);
|
||||
}
|
||||
|
||||
/*
|
||||
* Determine if there is space to add a body reply. First, we need to
|
||||
* verify that the client is finished sending the request. Next, there
|
||||
* needs to be enough space to send the headers already defined along
|
||||
* with the reply header (3 bytes) and the body header identifier
|
||||
* (3 bytes).
|
||||
*/
|
||||
|
||||
/* if ((finalBitSet) &&
|
||||
((bodyLength + 6 + headerArray.length) > maxPacketLength)) {
|
||||
|
||||
exceptionString = "Header larger then can be sent in a packet";
|
||||
isClosed = true;
|
||||
privateInput.close();
|
||||
if (privateOutput != null) {
|
||||
privateOutput.close();
|
||||
}
|
||||
parent.sendResponse(ResponseCodes.OBEX_HTTP_INTERNAL_ERROR,
|
||||
null);
|
||||
throw new IOException("OBEX Packet exceeds max packet size");
|
||||
}
|
||||
*/
|
||||
|
||||
if ((finalBitSet) || (headerArray.length < (maxPacketLength - 20))) {
|
||||
if ((finalBitSet) || (headerArray.length < (mMaxPacketLength - 20))) {
|
||||
if (bodyLength > 0) {
|
||||
/*
|
||||
* Determine if I can send the whole body or just part of
|
||||
* the body. Remember that there is the 3 bytes for the
|
||||
* response message and 3 bytes for the header ID and length
|
||||
*/
|
||||
if (bodyLength > (maxPacketLength - headerArray.length - 6)) {
|
||||
bodyLength = maxPacketLength - headerArray.length - 6;
|
||||
if (bodyLength > (mMaxPacketLength - headerArray.length - 6)) {
|
||||
bodyLength = mMaxPacketLength - headerArray.length - 6;
|
||||
}
|
||||
|
||||
byte[] body = privateOutput.readBytes(bodyLength);
|
||||
byte[] body = mPrivateOutput.readBytes(bodyLength);
|
||||
|
||||
/*
|
||||
* Since this is a put request if the final bit is set or
|
||||
* the output stream is closed we need to send the 0x49
|
||||
* (End of Body) otherwise, we need to send 0x48 (Body)
|
||||
*/
|
||||
if ((finalBitSet) || (privateOutput.isClosed())) {
|
||||
if ((finalBitSet) || (mPrivateOutput.isClosed())) {
|
||||
out.write(0x49);
|
||||
} else {
|
||||
out.write(0x48);
|
||||
@@ -430,44 +386,46 @@ public class ServerOperation implements Operation, BaseStream {
|
||||
|
||||
}
|
||||
|
||||
responseSize = 3;
|
||||
parent.sendResponse(type, out.toByteArray());
|
||||
mResponseSize = 3;
|
||||
mParent.sendResponse(type, out.toByteArray());
|
||||
|
||||
if (type == ObexHelper.OBEX_HTTP_CONTINUE) {
|
||||
int headerID = socketInput.read();
|
||||
int length = socketInput.read();
|
||||
length = (length << 8) + socketInput.read();
|
||||
if ((headerID != 0x02) && (headerID != 0x82) && (headerID != 0x03)
|
||||
&& (headerID != 0x83)) {
|
||||
if (type == ResponseCodes.OBEX_HTTP_CONTINUE) {
|
||||
int headerID = mInput.read();
|
||||
int length = mInput.read();
|
||||
length = (length << 8) + mInput.read();
|
||||
if ((headerID != ObexHelper.OBEX_OPCODE_PUT)
|
||||
&& (headerID != ObexHelper.OBEX_OPCODE_PUT_FINAL)
|
||||
&& (headerID != ObexHelper.OBEX_OPCODE_GET)
|
||||
&& (headerID != ObexHelper.OBEX_OPCODE_GET_FINAL)) {
|
||||
|
||||
if (length > 3) {
|
||||
byte[] temp = new byte[length];
|
||||
bytesReceived = socketInput.read(temp);
|
||||
bytesReceived = mInput.read(temp);
|
||||
|
||||
while (bytesReceived != length) {
|
||||
bytesReceived += socketInput.read(temp, bytesReceived, length
|
||||
- bytesReceived);
|
||||
bytesReceived += mInput.read(temp, bytesReceived, length - bytesReceived);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Determine if an ABORT was sent as the reply
|
||||
*/
|
||||
if (headerID == 0xFF) {
|
||||
parent.sendResponse(ResponseCodes.OBEX_HTTP_OK, null);
|
||||
isClosed = true;
|
||||
if (headerID == ObexHelper.OBEX_OPCODE_ABORT) {
|
||||
mParent.sendResponse(ResponseCodes.OBEX_HTTP_OK, null);
|
||||
mClosed = true;
|
||||
isAborted = true;
|
||||
exceptionString = "Abort Received";
|
||||
mExceptionString = "Abort Received";
|
||||
throw new IOException("Abort Received");
|
||||
} else {
|
||||
parent.sendResponse(ResponseCodes.OBEX_HTTP_BAD_REQUEST, null);
|
||||
isClosed = true;
|
||||
exceptionString = "Bad Request Received";
|
||||
mParent.sendResponse(ResponseCodes.OBEX_HTTP_BAD_REQUEST, null);
|
||||
mClosed = true;
|
||||
mExceptionString = "Bad Request Received";
|
||||
throw new IOException("Bad Request Received");
|
||||
}
|
||||
} else {
|
||||
|
||||
if ((headerID == 0x82) || (headerID == 0x83)) {
|
||||
if ((headerID == ObexHelper.OBEX_OPCODE_PUT_FINAL)
|
||||
|| (headerID == ObexHelper.OBEX_OPCODE_GET_FINAL)) {
|
||||
finalBitSet = true;
|
||||
}
|
||||
|
||||
@@ -475,7 +433,7 @@ public class ServerOperation implements Operation, BaseStream {
|
||||
* Determine if the packet length is larger then this device can receive
|
||||
*/
|
||||
if (length > ObexHelper.MAX_PACKET_SIZE_INT) {
|
||||
parent.sendResponse(ResponseCodes.OBEX_HTTP_REQ_TOO_LARGE, null);
|
||||
mParent.sendResponse(ResponseCodes.OBEX_HTTP_REQ_TOO_LARGE, null);
|
||||
throw new IOException("Packet received was too large");
|
||||
}
|
||||
|
||||
@@ -484,54 +442,46 @@ public class ServerOperation implements Operation, BaseStream {
|
||||
*/
|
||||
if (length > 3) {
|
||||
byte[] data = new byte[length - 3];
|
||||
bytesReceived = socketInput.read(data);
|
||||
bytesReceived = mInput.read(data);
|
||||
|
||||
while (bytesReceived != data.length) {
|
||||
bytesReceived += socketInput.read(data, bytesReceived, data.length
|
||||
bytesReceived += mInput.read(data, bytesReceived, data.length
|
||||
- bytesReceived);
|
||||
}
|
||||
byte[] body = ObexHelper.updateHeaderSet(requestHeaders, data);
|
||||
byte[] body = ObexHelper.updateHeaderSet(requestHeader, data);
|
||||
if (body != null) {
|
||||
isHasBody = true;
|
||||
mHasBody = true;
|
||||
}
|
||||
if (requestHeaders.connectionID != null) {
|
||||
listener.setConnectionID(ObexHelper
|
||||
.convertToLong(requestHeaders.connectionID));
|
||||
if (requestHeader.mConnectionID != null) {
|
||||
mListener.setConnectionId(ObexHelper
|
||||
.convertToLong(requestHeader.mConnectionID));
|
||||
} else {
|
||||
listener.setConnectionID(1);
|
||||
mListener.setConnectionId(1);
|
||||
}
|
||||
|
||||
if (requestHeaders.authResp != null) {
|
||||
if (!parent.handleAuthResp(requestHeaders.authResp)) {
|
||||
exceptionString = "Authentication Failed";
|
||||
parent.sendResponse(ResponseCodes.OBEX_HTTP_UNAUTHORIZED, null);
|
||||
isClosed = true;
|
||||
requestHeaders.authResp = null;
|
||||
if (requestHeader.mAuthResp != null) {
|
||||
if (!mParent.handleAuthResp(requestHeader.mAuthResp)) {
|
||||
mExceptionString = "Authentication Failed";
|
||||
mParent.sendResponse(ResponseCodes.OBEX_HTTP_UNAUTHORIZED, null);
|
||||
mClosed = true;
|
||||
requestHeader.mAuthResp = null;
|
||||
return false;
|
||||
}
|
||||
requestHeaders.authResp = null;
|
||||
requestHeader.mAuthResp = null;
|
||||
}
|
||||
|
||||
if (requestHeaders.authChall != null) {
|
||||
parent.handleAuthChall(requestHeaders);
|
||||
if (requestHeader.mAuthChall != null) {
|
||||
mParent.handleAuthChall(requestHeader);
|
||||
// send the auhtResp to the client
|
||||
replyHeaders.authResp = new byte[requestHeaders.authResp.length];
|
||||
System.arraycopy(requestHeaders.authResp, 0, replyHeaders.authResp, 0,
|
||||
replyHeaders.authResp.length);
|
||||
requestHeaders.authResp = null;
|
||||
requestHeaders.authChall = null;
|
||||
replyHeader.mAuthResp = new byte[requestHeader.mAuthResp.length];
|
||||
System.arraycopy(requestHeader.mAuthResp, 0, replyHeader.mAuthResp, 0,
|
||||
replyHeader.mAuthResp.length);
|
||||
requestHeader.mAuthResp = null;
|
||||
requestHeader.mAuthChall = null;
|
||||
}
|
||||
|
||||
if (body != null) {
|
||||
if (body[0] == 0x49) {
|
||||
endOfBody = true;
|
||||
}
|
||||
|
||||
/*byte [] body_tmp = new byte[body.length-1];
|
||||
System.arraycopy(body,1,body_tmp,0,body.length-1);
|
||||
privateInput.writeBytes(body_tmp, body.length-1);*/
|
||||
privateInput.writeBytes(body, 1);
|
||||
|
||||
mPrivateInput.writeBytes(body, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -562,9 +512,9 @@ public class ServerOperation implements Operation, BaseStream {
|
||||
*
|
||||
* @throws IOException if this <code>Operation</code> has been closed
|
||||
*/
|
||||
public HeaderSet getReceivedHeaders() throws IOException {
|
||||
public HeaderSet getReceivedHeader() throws IOException {
|
||||
ensureOpen();
|
||||
return requestHeaders;
|
||||
return requestHeader;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -583,13 +533,13 @@ public class ServerOperation implements Operation, BaseStream {
|
||||
ensureOpen();
|
||||
|
||||
if (headers == null) {
|
||||
throw new NullPointerException("Headers may not be null");
|
||||
throw new IOException("Headers may not be null");
|
||||
}
|
||||
|
||||
int[] headerList = headers.getHeaderList();
|
||||
if (headerList != null) {
|
||||
for (int i = 0; i < headerList.length; i++) {
|
||||
replyHeaders.setHeader(headerList[i], headers.getHeader(headerList[i]));
|
||||
replyHeader.setHeader(headerList[i], headers.getHeader(headerList[i]));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -629,7 +579,7 @@ public class ServerOperation implements Operation, BaseStream {
|
||||
*/
|
||||
public String getType() {
|
||||
try {
|
||||
return (String)requestHeaders.getHeader(HeaderSet.TYPE);
|
||||
return (String)requestHeader.getHeader(HeaderSet.TYPE);
|
||||
} catch (IOException e) {
|
||||
return null;
|
||||
}
|
||||
@@ -645,7 +595,7 @@ public class ServerOperation implements Operation, BaseStream {
|
||||
*/
|
||||
public long getLength() {
|
||||
try {
|
||||
Long temp = (Long)requestHeaders.getHeader(HeaderSet.LENGTH);
|
||||
Long temp = (Long)requestHeader.getHeader(HeaderSet.LENGTH);
|
||||
|
||||
if (temp == null) {
|
||||
return -1;
|
||||
@@ -658,7 +608,7 @@ public class ServerOperation implements Operation, BaseStream {
|
||||
}
|
||||
|
||||
public int getMaxPacketSize() {
|
||||
return maxPacketLength - 6;
|
||||
return mMaxPacketLength - 6;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -670,7 +620,7 @@ public class ServerOperation implements Operation, BaseStream {
|
||||
*/
|
||||
public InputStream openInputStream() throws IOException {
|
||||
ensureOpen();
|
||||
return privateInput;
|
||||
return mPrivateInput;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -694,17 +644,19 @@ public class ServerOperation implements Operation, BaseStream {
|
||||
public OutputStream openOutputStream() throws IOException {
|
||||
ensureOpen();
|
||||
|
||||
if (outputStreamOpened)
|
||||
if (mPrivateOutputOpen) {
|
||||
throw new IOException("no more input streams available, stream already opened");
|
||||
|
||||
if (!requestFinished)
|
||||
throw new IOException("no output streams available ,request not finished");
|
||||
|
||||
if (privateOutput == null) {
|
||||
privateOutput = new PrivateOutputStream(this, maxPacketLength - 6);
|
||||
}
|
||||
outputStreamOpened = true;
|
||||
return privateOutput;
|
||||
|
||||
if (!mRequestFinished) {
|
||||
throw new IOException("no output streams available ,request not finished");
|
||||
}
|
||||
|
||||
if (mPrivateOutput == null) {
|
||||
mPrivateOutput = new PrivateOutputStream(this, mMaxPacketLength - 6);
|
||||
}
|
||||
mPrivateOutputOpen = true;
|
||||
return mPrivateOutput;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -725,7 +677,7 @@ public class ServerOperation implements Operation, BaseStream {
|
||||
*/
|
||||
public void close() throws IOException {
|
||||
ensureOpen();
|
||||
isClosed = true;
|
||||
mClosed = true;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -734,10 +686,10 @@ public class ServerOperation implements Operation, BaseStream {
|
||||
* @throws IOException if an exception needs to be thrown
|
||||
*/
|
||||
public void ensureOpen() throws IOException {
|
||||
if (exceptionString != null) {
|
||||
throw new IOException(exceptionString);
|
||||
if (mExceptionString != null) {
|
||||
throw new IOException(mExceptionString);
|
||||
}
|
||||
if (isClosed) {
|
||||
if (mClosed) {
|
||||
throw new IOException("Operation has already ended");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -71,7 +71,7 @@ package javax.obex;
|
||||
*/
|
||||
public class ServerRequestHandler {
|
||||
|
||||
private long connectionID;
|
||||
private long mConnectionId;
|
||||
|
||||
/**
|
||||
* Creates a <code>ServerRequestHandler</code>.
|
||||
@@ -80,33 +80,23 @@ public class ServerRequestHandler {
|
||||
/*
|
||||
* A connection ID of -1 implies there is no conenction ID
|
||||
*/
|
||||
connectionID = -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a <code>HeaderSet</code> object that may be used in put and get
|
||||
* operations.
|
||||
*
|
||||
* @return the <code>HeaderSet</code> object to use in put and get operations
|
||||
*/
|
||||
public final HeaderSet createHeaderSet() {
|
||||
return new HeaderSet();
|
||||
mConnectionId = -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the connection ID header to include in the reply packets.
|
||||
*
|
||||
* @param id the connection ID to use; -1 if no connection ID should be
|
||||
* @param connectionId the connection ID to use; -1 if no connection ID should be
|
||||
* sent
|
||||
*
|
||||
* @throws IllegalArgumentException if <code>id</code> is not in the
|
||||
* range -1 to 2<sup>32</sup>-1
|
||||
*/
|
||||
public void setConnectionID(long id) {
|
||||
if ((id < -1) || (id > 0xFFFFFFFFL)) {
|
||||
public void setConnectionId(final long connectionId) {
|
||||
if ((connectionId < -1) || (connectionId > 0xFFFFFFFFL)) {
|
||||
throw new IllegalArgumentException("Illegal Connection ID");
|
||||
}
|
||||
connectionID = id;
|
||||
mConnectionId = connectionId;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -116,8 +106,8 @@ public class ServerRequestHandler {
|
||||
* @return the connection id being used or -1 if no connection ID is being
|
||||
* used
|
||||
*/
|
||||
public long getConnectionID() {
|
||||
return connectionID;
|
||||
public long getConnectionId() {
|
||||
return mConnectionId;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -231,7 +221,7 @@ public class ServerRequestHandler {
|
||||
* If an ABORT request is received during the processing of a PUT request,
|
||||
* <code>op</code> will be closed by the implementation.
|
||||
*
|
||||
* @param op contains the headers sent by the client and allows new
|
||||
* @param operation contains the headers sent by the client and allows new
|
||||
* headers to be sent in the reply; <code>op</code> will never be
|
||||
* <code>null</code>
|
||||
*
|
||||
@@ -239,7 +229,7 @@ public class ServerRequestHandler {
|
||||
* returned to the client; if an invalid response code is provided, the
|
||||
* <code>OBEX_HTTP_INTERNAL_ERROR</code> response code will be used
|
||||
*/
|
||||
public int onPut(Operation op) {
|
||||
public int onPut(Operation operation) {
|
||||
return ResponseCodes.OBEX_HTTP_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
@@ -253,7 +243,7 @@ public class ServerRequestHandler {
|
||||
* If an ABORT request is received during the processing of a GET request,
|
||||
* <code>op</code> will be closed by the implementation.
|
||||
*
|
||||
* @param op contains the headers sent by the client and allows new
|
||||
* @param operation contains the headers sent by the client and allows new
|
||||
* headers to be sent in the reply; <code>op</code> will never be
|
||||
* <code>null</code>
|
||||
*
|
||||
@@ -261,7 +251,7 @@ public class ServerRequestHandler {
|
||||
* returned to the client; if an invalid response code is provided, the
|
||||
* <code>OBEX_HTTP_INTERNAL_ERROR</code> response code will be used
|
||||
*/
|
||||
public int onGet(Operation op) {
|
||||
public int onGet(Operation operation) {
|
||||
return ResponseCodes.OBEX_HTTP_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
@@ -279,10 +269,23 @@ public class ServerRequestHandler {
|
||||
public void onAuthenticationFailure(byte[] userName) {
|
||||
}
|
||||
|
||||
/**Called by ServerSession to update the status of current transaction */
|
||||
/**
|
||||
* Called by ServerSession to update the status of current transaction
|
||||
* <P>
|
||||
* If this method is not implemented by the class that extends this class,
|
||||
* this method will do nothing.
|
||||
*
|
||||
*/
|
||||
public void updateStatus(String message) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when session is closed.
|
||||
* <P>
|
||||
* If this method is not implemented by the class that extends this class,
|
||||
* this method will do nothing.
|
||||
*
|
||||
*/
|
||||
public void onClose() {
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,39 +32,39 @@
|
||||
|
||||
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 ServerSession interface.
|
||||
* This class in an implementation of the OBEX ServerSession.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public class ServerSession implements Runnable, ObexSession {
|
||||
public final class ServerSession extends ObexSession implements Runnable {
|
||||
|
||||
private ObexTransport client;
|
||||
private static final String TAG = "Obex ServerSession";
|
||||
|
||||
private InputStream input;
|
||||
private ObexTransport mTransport;
|
||||
|
||||
private OutputStream output;
|
||||
private InputStream mInput;
|
||||
|
||||
private ServerRequestHandler listener;
|
||||
private OutputStream mOutput;
|
||||
|
||||
private Thread processThread;
|
||||
private ServerRequestHandler mListener;
|
||||
|
||||
private int maxPacketLength;
|
||||
private Thread mProcessThread;
|
||||
|
||||
private Authenticator authenticator;
|
||||
private int mMaxPacketLength;
|
||||
|
||||
byte[] challengeDigest;
|
||||
|
||||
private boolean isClosed;
|
||||
private boolean mClosed;
|
||||
|
||||
/**
|
||||
* Creates new ServerSession.
|
||||
*
|
||||
* @param conn
|
||||
* @param trans
|
||||
* the connection to the client
|
||||
*
|
||||
* @param handler
|
||||
@@ -77,50 +77,20 @@ public class ServerSession implements Runnable, ObexSession {
|
||||
* if an error occurred while opening the input and output
|
||||
* streams
|
||||
*/
|
||||
public ServerSession(ObexTransport conn, ServerRequestHandler handler, Authenticator auth)
|
||||
public ServerSession(ObexTransport trans, ServerRequestHandler handler, Authenticator auth)
|
||||
throws IOException {
|
||||
authenticator = auth;
|
||||
client = conn;
|
||||
input = client.openInputStream();
|
||||
output = client.openOutputStream();
|
||||
listener = handler;
|
||||
maxPacketLength = 256;
|
||||
mAuthenticator = auth;
|
||||
mTransport = trans;
|
||||
mInput = mTransport.openInputStream();
|
||||
mOutput = mTransport.openOutputStream();
|
||||
mListener = handler;
|
||||
mMaxPacketLength = 256;
|
||||
|
||||
isClosed = false;
|
||||
processThread = new Thread(this);
|
||||
processThread.start();
|
||||
mClosed = false;
|
||||
mProcessThread = new Thread(this);
|
||||
mProcessThread.start();
|
||||
}
|
||||
|
||||
/* removed as they're provided to the API user. Not used internally. */
|
||||
/*
|
||||
public boolean isCreatedServer() {
|
||||
if (client instanceof BTConnection)
|
||||
return ((BTConnection)client).isServerCreated();
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean isClosed() {
|
||||
if (client instanceof BTConnection)
|
||||
return ((BTConnection)client).isClosed();
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
public int getConnectionHandle() {
|
||||
if (client instanceof BTConnection)
|
||||
return ((BTConnection)client).getConnectionHandle();
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
|
||||
public RemoteDevice getRemoteDevice() {
|
||||
if (client instanceof BTConnection)
|
||||
return ((BTConnection)client).getRemoteDevice();
|
||||
else
|
||||
return null;
|
||||
}*/
|
||||
|
||||
/**
|
||||
* Processes requests made to the server and forwards them to the
|
||||
* appropriate event listener.
|
||||
@@ -129,29 +99,29 @@ public class ServerSession implements Runnable, ObexSession {
|
||||
try {
|
||||
|
||||
boolean done = false;
|
||||
while (!done && !isClosed) {
|
||||
int requestType = input.read();
|
||||
while (!done && !mClosed) {
|
||||
int requestType = mInput.read();
|
||||
switch (requestType) {
|
||||
case 0x80:
|
||||
case ObexHelper.OBEX_OPCODE_CONNECT:
|
||||
handleConnectRequest();
|
||||
break;
|
||||
|
||||
case 0x81:
|
||||
case ObexHelper.OBEX_OPCODE_DISCONNECT:
|
||||
handleDisconnectRequest();
|
||||
done = true;
|
||||
break;
|
||||
|
||||
case 0x03:
|
||||
case 0x83:
|
||||
case ObexHelper.OBEX_OPCODE_GET:
|
||||
case ObexHelper.OBEX_OPCODE_GET_FINAL:
|
||||
handleGetRequest(requestType);
|
||||
break;
|
||||
|
||||
case 0x02:
|
||||
case 0x82:
|
||||
case ObexHelper.OBEX_OPCODE_PUT:
|
||||
case ObexHelper.OBEX_OPCODE_PUT_FINAL:
|
||||
handlePutRequest(requestType);
|
||||
break;
|
||||
|
||||
case 0x85:
|
||||
case ObexHelper.OBEX_OPCODE_SETPATH:
|
||||
handleSetPathRequest();
|
||||
break;
|
||||
|
||||
@@ -166,19 +136,19 @@ public class ServerSession implements Runnable, ObexSession {
|
||||
* just going to read the packet and send a not implemented
|
||||
* to the client
|
||||
*/
|
||||
int length = input.read();
|
||||
length = (length << 8) + input.read();
|
||||
int length = mInput.read();
|
||||
length = (length << 8) + mInput.read();
|
||||
for (int i = 3; i < length; i++) {
|
||||
input.read();
|
||||
mInput.read();
|
||||
}
|
||||
sendResponse(ResponseCodes.OBEX_HTTP_NOT_IMPLEMENTED, null);
|
||||
|
||||
// done = true;
|
||||
}
|
||||
}
|
||||
|
||||
} catch (NullPointerException e) {
|
||||
Log.d(TAG, e.toString());
|
||||
} catch (Exception e) {
|
||||
Log.d(TAG, e.toString());
|
||||
}
|
||||
close();
|
||||
}
|
||||
@@ -201,24 +171,24 @@ public class ServerSession implements Runnable, ObexSession {
|
||||
* if an error occurred at the transport layer
|
||||
*/
|
||||
private void handlePutRequest(int type) throws IOException {
|
||||
ServerOperation client = new ServerOperation(this, input, type, maxPacketLength, listener);
|
||||
ServerOperation op = new ServerOperation(this, mInput, type, mMaxPacketLength, mListener);
|
||||
try {
|
||||
int response = -1;
|
||||
|
||||
if ((client.finalBitSet) && !client.isValidBody()) {
|
||||
response = validateResponseCode(listener.onDelete(client.requestHeaders,
|
||||
client.replyHeaders));
|
||||
if ((op.finalBitSet) && !op.isValidBody()) {
|
||||
response = validateResponseCode(mListener
|
||||
.onDelete(op.requestHeader, op.replyHeader));
|
||||
} else {
|
||||
response = validateResponseCode(listener.onPut(client));
|
||||
response = validateResponseCode(mListener.onPut(op));
|
||||
}
|
||||
if (response != ResponseCodes.OBEX_HTTP_OK) {
|
||||
client.sendReply(response);
|
||||
} else if (!client.isAborted) {
|
||||
op.sendReply(response);
|
||||
} else if (!op.isAborted) {
|
||||
// wait for the final bit
|
||||
while (!client.finalBitSet) {
|
||||
client.sendReply(ObexHelper.OBEX_HTTP_CONTINUE);
|
||||
while (!op.finalBitSet) {
|
||||
op.sendReply(ResponseCodes.OBEX_HTTP_CONTINUE);
|
||||
}
|
||||
client.sendReply(response);
|
||||
op.sendReply(response);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
sendResponse(ResponseCodes.OBEX_HTTP_INTERNAL_ERROR, null);
|
||||
@@ -243,12 +213,12 @@ public class ServerSession implements Runnable, ObexSession {
|
||||
* if an error occurred at the transport layer
|
||||
*/
|
||||
private void handleGetRequest(int type) throws IOException {
|
||||
ServerOperation client = new ServerOperation(this, input, type, maxPacketLength, listener);
|
||||
ServerOperation op = new ServerOperation(this, mInput, type, mMaxPacketLength, mListener);
|
||||
try {
|
||||
int response = validateResponseCode(listener.onGet(client));
|
||||
int response = validateResponseCode(mListener.onGet(op));
|
||||
|
||||
if (!client.isAborted) {
|
||||
client.sendReply(response);
|
||||
if (!op.isAborted) {
|
||||
op.sendReply(response);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
sendResponse(ResponseCodes.OBEX_HTTP_INTERNAL_ERROR, null);
|
||||
@@ -267,7 +237,7 @@ public class ServerSession implements Runnable, ObexSession {
|
||||
* @throws IOException
|
||||
* if an IO error occurs
|
||||
*/
|
||||
protected void sendResponse(int code, byte[] header) throws IOException {
|
||||
public void sendResponse(int code, byte[] header) throws IOException {
|
||||
int totalLength = 3;
|
||||
byte[] data = null;
|
||||
|
||||
@@ -284,8 +254,8 @@ public class ServerSession implements Runnable, ObexSession {
|
||||
data[1] = (byte)0x00;
|
||||
data[2] = (byte)totalLength;
|
||||
}
|
||||
output.write(data);
|
||||
output.flush();
|
||||
mOutput.write(data);
|
||||
mOutput.flush();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -302,6 +272,7 @@ public class ServerSession implements Runnable, ObexSession {
|
||||
private void handleSetPathRequest() throws IOException {
|
||||
int length;
|
||||
int flags;
|
||||
@SuppressWarnings("unused")
|
||||
int constants;
|
||||
int totalLength = 3;
|
||||
byte[] head = null;
|
||||
@@ -310,10 +281,10 @@ public class ServerSession implements Runnable, ObexSession {
|
||||
HeaderSet request = new HeaderSet();
|
||||
HeaderSet reply = new HeaderSet();
|
||||
|
||||
length = input.read();
|
||||
length = (length << 8) + input.read();
|
||||
flags = input.read();
|
||||
constants = input.read();
|
||||
length = mInput.read();
|
||||
length = (length << 8) + mInput.read();
|
||||
flags = mInput.read();
|
||||
constants = mInput.read();
|
||||
|
||||
if (length > ObexHelper.MAX_PACKET_SIZE_INT) {
|
||||
code = ResponseCodes.OBEX_HTTP_REQ_TOO_LARGE;
|
||||
@@ -321,41 +292,41 @@ public class ServerSession implements Runnable, ObexSession {
|
||||
} else {
|
||||
if (length > 5) {
|
||||
byte[] headers = new byte[length - 5];
|
||||
bytesReceived = input.read(headers);
|
||||
bytesReceived = mInput.read(headers);
|
||||
|
||||
while (bytesReceived != headers.length) {
|
||||
bytesReceived += input.read(headers, bytesReceived, headers.length
|
||||
bytesReceived += mInput.read(headers, bytesReceived, headers.length
|
||||
- bytesReceived);
|
||||
}
|
||||
|
||||
ObexHelper.updateHeaderSet(request, headers);
|
||||
|
||||
if (request.connectionID != null) {
|
||||
listener.setConnectionID(ObexHelper.convertToLong(request.connectionID));
|
||||
if (request.mConnectionID != null) {
|
||||
mListener.setConnectionId(ObexHelper.convertToLong(request.mConnectionID));
|
||||
} else {
|
||||
listener.setConnectionID(-1);
|
||||
mListener.setConnectionId(-1);
|
||||
}
|
||||
// the Auth chan is initiated by the server.
|
||||
// client sent back the authResp .
|
||||
if (request.authResp != null) {
|
||||
if (!handleAuthResp(request.authResp)) {
|
||||
// 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;
|
||||
listener.onAuthenticationFailure(ObexHelper.getTagValue((byte)0x01,
|
||||
request.authResp));
|
||||
mListener.onAuthenticationFailure(ObexHelper.getTagValue((byte)0x01,
|
||||
request.mAuthResp));
|
||||
}
|
||||
request.authResp = null;
|
||||
request.mAuthResp = null;
|
||||
}
|
||||
}
|
||||
|
||||
if (code != ResponseCodes.OBEX_HTTP_UNAUTHORIZED) {
|
||||
// the Auth chan is initiated by the client
|
||||
// the Auth challenge is initiated by the client
|
||||
// the server will send back the authResp to the client
|
||||
if (request.authChall != null) {
|
||||
if (request.mAuthChall != null) {
|
||||
handleAuthChall(request);
|
||||
reply.authResp = new byte[request.authResp.length];
|
||||
System.arraycopy(request.authResp, 0, reply.authResp, 0, reply.authResp.length);
|
||||
request.authChall = null;
|
||||
request.authResp = null;
|
||||
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;
|
||||
@@ -367,7 +338,7 @@ public class ServerSession implements Runnable, ObexSession {
|
||||
}
|
||||
|
||||
try {
|
||||
code = listener.onSetPath(request, reply, backup, create);
|
||||
code = mListener.onSetPath(request, reply, backup, create);
|
||||
} catch (Exception e) {
|
||||
sendResponse(ResponseCodes.OBEX_HTTP_INTERNAL_ERROR, null);
|
||||
return;
|
||||
@@ -376,23 +347,23 @@ public class ServerSession implements Runnable, ObexSession {
|
||||
code = validateResponseCode(code);
|
||||
|
||||
if (reply.nonce != null) {
|
||||
challengeDigest = new byte[16];
|
||||
System.arraycopy(reply.nonce, 0, challengeDigest, 0, 16);
|
||||
mChallengeDigest = new byte[16];
|
||||
System.arraycopy(reply.nonce, 0, mChallengeDigest, 0, 16);
|
||||
} else {
|
||||
challengeDigest = null;
|
||||
mChallengeDigest = null;
|
||||
}
|
||||
|
||||
long id = listener.getConnectionID();
|
||||
long id = mListener.getConnectionId();
|
||||
if (id == -1) {
|
||||
reply.connectionID = null;
|
||||
reply.mConnectionID = null;
|
||||
} else {
|
||||
reply.connectionID = ObexHelper.convertToByteArray(id);
|
||||
reply.mConnectionID = ObexHelper.convertToByteArray(id);
|
||||
}
|
||||
|
||||
head = ObexHelper.createHeader(reply, false);
|
||||
totalLength += head.length;
|
||||
|
||||
if (totalLength > maxPacketLength) {
|
||||
if (totalLength > mMaxPacketLength) {
|
||||
totalLength = 3;
|
||||
head = null;
|
||||
code = ResponseCodes.OBEX_HTTP_INTERNAL_ERROR;
|
||||
@@ -412,8 +383,8 @@ public class ServerSession implements Runnable, ObexSession {
|
||||
* Write the OBEX SETPATH packet to the server. Byte 0: response code
|
||||
* Byte 1&2: Connect Packet Length Byte 3 to n: headers
|
||||
*/
|
||||
output.write(replyData);
|
||||
output.flush();
|
||||
mOutput.write(replyData);
|
||||
mOutput.flush();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -435,8 +406,8 @@ public class ServerSession implements Runnable, ObexSession {
|
||||
HeaderSet request = new HeaderSet();
|
||||
HeaderSet reply = new HeaderSet();
|
||||
|
||||
length = input.read();
|
||||
length = (length << 8) + input.read();
|
||||
length = mInput.read();
|
||||
length = (length << 8) + mInput.read();
|
||||
|
||||
if (length > ObexHelper.MAX_PACKET_SIZE_INT) {
|
||||
code = ResponseCodes.OBEX_HTTP_REQ_TOO_LARGE;
|
||||
@@ -444,66 +415,56 @@ public class ServerSession implements Runnable, ObexSession {
|
||||
} else {
|
||||
if (length > 3) {
|
||||
byte[] headers = new byte[length - 3];
|
||||
bytesReceived = input.read(headers);
|
||||
bytesReceived = mInput.read(headers);
|
||||
|
||||
while (bytesReceived != headers.length) {
|
||||
bytesReceived += input.read(headers, bytesReceived, headers.length
|
||||
bytesReceived += mInput.read(headers, bytesReceived, headers.length
|
||||
- bytesReceived);
|
||||
}
|
||||
|
||||
ObexHelper.updateHeaderSet(request, headers);
|
||||
}
|
||||
|
||||
if (request.connectionID != null) {
|
||||
listener.setConnectionID(ObexHelper.convertToLong(request.connectionID));
|
||||
if (request.mConnectionID != null) {
|
||||
mListener.setConnectionId(ObexHelper.convertToLong(request.mConnectionID));
|
||||
} else {
|
||||
listener.setConnectionID(1);
|
||||
mListener.setConnectionId(1);
|
||||
}
|
||||
|
||||
if (request.authResp != null) {
|
||||
if (!handleAuthResp(request.authResp)) {
|
||||
if (request.mAuthResp != null) {
|
||||
if (!handleAuthResp(request.mAuthResp)) {
|
||||
code = ResponseCodes.OBEX_HTTP_UNAUTHORIZED;
|
||||
listener.onAuthenticationFailure(ObexHelper.getTagValue((byte)0x01,
|
||||
request.authResp));
|
||||
mListener.onAuthenticationFailure(ObexHelper.getTagValue((byte)0x01,
|
||||
request.mAuthResp));
|
||||
}
|
||||
request.authResp = null;
|
||||
request.mAuthResp = null;
|
||||
}
|
||||
|
||||
if (code != ResponseCodes.OBEX_HTTP_UNAUTHORIZED) {
|
||||
|
||||
if (request.authChall != null) {
|
||||
if (request.mAuthChall != null) {
|
||||
handleAuthChall(request);
|
||||
request.authChall = null;
|
||||
request.mAuthChall = null;
|
||||
}
|
||||
|
||||
try {
|
||||
listener.onDisconnect(request, reply);
|
||||
mListener.onDisconnect(request, reply);
|
||||
} catch (Exception e) {
|
||||
sendResponse(ResponseCodes.OBEX_HTTP_INTERNAL_ERROR, null);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Since a client will never response to an authentication
|
||||
* challenge on a DISCONNECT, there is no reason to keep track
|
||||
* of the challenge.
|
||||
*
|
||||
* if (reply.nonce != null) { challengeDigest = new byte[16];
|
||||
* System.arraycopy(reply.nonce, 0, challengeDigest, 0, 16); }
|
||||
* else { challengeDigest = null; }
|
||||
*/
|
||||
|
||||
long id = listener.getConnectionID();
|
||||
long id = mListener.getConnectionId();
|
||||
if (id == -1) {
|
||||
reply.connectionID = null;
|
||||
reply.mConnectionID = null;
|
||||
} else {
|
||||
reply.connectionID = ObexHelper.convertToByteArray(id);
|
||||
reply.mConnectionID = ObexHelper.convertToByteArray(id);
|
||||
}
|
||||
|
||||
head = ObexHelper.createHeader(reply, false);
|
||||
totalLength += head.length;
|
||||
|
||||
if (totalLength > maxPacketLength) {
|
||||
if (totalLength > mMaxPacketLength) {
|
||||
totalLength = 3;
|
||||
head = null;
|
||||
code = ResponseCodes.OBEX_HTTP_INTERNAL_ERROR;
|
||||
@@ -528,8 +489,8 @@ public class ServerSession implements Runnable, ObexSession {
|
||||
* Write the OBEX DISCONNECT packet to the server. Byte 0: response code
|
||||
* Byte 1&2: Connect Packet Length Byte 3 to n: headers
|
||||
*/
|
||||
output.write(replyData);
|
||||
output.flush();
|
||||
mOutput.write(replyData);
|
||||
mOutput.flush();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -545,7 +506,9 @@ public class ServerSession implements Runnable, ObexSession {
|
||||
*/
|
||||
private void handleConnectRequest() throws IOException {
|
||||
int packetLength;
|
||||
@SuppressWarnings("unused")
|
||||
int version;
|
||||
@SuppressWarnings("unused")
|
||||
int flags;
|
||||
int totalLength = 7;
|
||||
byte[] head = null;
|
||||
@@ -558,16 +521,16 @@ public class ServerSession implements Runnable, ObexSession {
|
||||
* Read in the length of the OBEX packet, OBEX version, flags, and max
|
||||
* packet length
|
||||
*/
|
||||
packetLength = input.read();
|
||||
packetLength = (packetLength << 8) + input.read();
|
||||
version = input.read();
|
||||
flags = input.read();
|
||||
maxPacketLength = input.read();
|
||||
maxPacketLength = (maxPacketLength << 8) + input.read();
|
||||
packetLength = mInput.read();
|
||||
packetLength = (packetLength << 8) + mInput.read();
|
||||
version = mInput.read();
|
||||
flags = mInput.read();
|
||||
mMaxPacketLength = mInput.read();
|
||||
mMaxPacketLength = (mMaxPacketLength << 8) + mInput.read();
|
||||
|
||||
// should we check it?
|
||||
if (maxPacketLength > ObexHelper.MAX_PACKET_SIZE_INT) {
|
||||
maxPacketLength = ObexHelper.MAX_PACKET_SIZE_INT;
|
||||
if (mMaxPacketLength > ObexHelper.MAX_PACKET_SIZE_INT) {
|
||||
mMaxPacketLength = ObexHelper.MAX_PACKET_SIZE_INT;
|
||||
}
|
||||
|
||||
if (packetLength > ObexHelper.MAX_PACKET_SIZE_INT) {
|
||||
@@ -576,61 +539,62 @@ public class ServerSession implements Runnable, ObexSession {
|
||||
} else {
|
||||
if (packetLength > 7) {
|
||||
byte[] headers = new byte[packetLength - 7];
|
||||
bytesReceived = input.read(headers);
|
||||
bytesReceived = mInput.read(headers);
|
||||
|
||||
while (bytesReceived != headers.length) {
|
||||
bytesReceived += input.read(headers, bytesReceived, headers.length
|
||||
bytesReceived += mInput.read(headers, bytesReceived, headers.length
|
||||
- bytesReceived);
|
||||
}
|
||||
|
||||
ObexHelper.updateHeaderSet(request, headers);
|
||||
}
|
||||
|
||||
if (request.connectionID != null) {
|
||||
listener.setConnectionID(ObexHelper.convertToLong(request.connectionID));
|
||||
if (request.mConnectionID != null) {
|
||||
mListener.setConnectionId(ObexHelper.convertToLong(request.mConnectionID));
|
||||
} else {
|
||||
listener.setConnectionID(1);
|
||||
mListener.setConnectionId(1);
|
||||
}
|
||||
|
||||
if (request.authResp != null) {
|
||||
if (!handleAuthResp(request.authResp)) {
|
||||
if (request.mAuthResp != null) {
|
||||
if (!handleAuthResp(request.mAuthResp)) {
|
||||
code = ResponseCodes.OBEX_HTTP_UNAUTHORIZED;
|
||||
listener.onAuthenticationFailure(ObexHelper.getTagValue((byte)0x01,
|
||||
request.authResp));
|
||||
mListener.onAuthenticationFailure(ObexHelper.getTagValue((byte)0x01,
|
||||
request.mAuthResp));
|
||||
}
|
||||
request.authResp = null;
|
||||
request.mAuthResp = null;
|
||||
}
|
||||
|
||||
if (code != ResponseCodes.OBEX_HTTP_UNAUTHORIZED) {
|
||||
if (request.authChall != null) {
|
||||
if (request.mAuthChall != null) {
|
||||
handleAuthChall(request);
|
||||
reply.authResp = new byte[request.authResp.length];
|
||||
System.arraycopy(request.authResp, 0, reply.authResp, 0, reply.authResp.length);
|
||||
request.authChall = null;
|
||||
request.authResp = null;
|
||||
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 = listener.onConnect(request, reply);
|
||||
code = mListener.onConnect(request, reply);
|
||||
code = validateResponseCode(code);
|
||||
|
||||
if (reply.nonce != null) {
|
||||
challengeDigest = new byte[16];
|
||||
System.arraycopy(reply.nonce, 0, challengeDigest, 0, 16);
|
||||
mChallengeDigest = new byte[16];
|
||||
System.arraycopy(reply.nonce, 0, mChallengeDigest, 0, 16);
|
||||
} else {
|
||||
challengeDigest = null;
|
||||
mChallengeDigest = null;
|
||||
}
|
||||
long id = listener.getConnectionID();
|
||||
long id = mListener.getConnectionId();
|
||||
if (id == -1) {
|
||||
reply.connectionID = null;
|
||||
reply.mConnectionID = null;
|
||||
} else {
|
||||
reply.connectionID = ObexHelper.convertToByteArray(id);
|
||||
reply.mConnectionID = ObexHelper.convertToByteArray(id);
|
||||
}
|
||||
|
||||
head = ObexHelper.createHeader(reply, false);
|
||||
totalLength += head.length;
|
||||
|
||||
if (totalLength > maxPacketLength) {
|
||||
if (totalLength > mMaxPacketLength) {
|
||||
totalLength = 7;
|
||||
head = null;
|
||||
code = ResponseCodes.OBEX_HTTP_INTERNAL_ERROR;
|
||||
@@ -667,8 +631,8 @@ public class ServerSession implements Runnable, ObexSession {
|
||||
System.arraycopy(head, 0, sendData, 7, head.length);
|
||||
}
|
||||
|
||||
output.write(sendData);
|
||||
output.flush();
|
||||
mOutput.write(sendData);
|
||||
mOutput.flush();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -677,20 +641,20 @@ public class ServerSession implements Runnable, ObexSession {
|
||||
* attempt to read/write will throw an exception.
|
||||
*/
|
||||
public synchronized void close() {
|
||||
if (listener != null) {
|
||||
listener.onClose();
|
||||
if (mListener != null) {
|
||||
mListener.onClose();
|
||||
}
|
||||
try {
|
||||
input.close();
|
||||
output.close();
|
||||
client.close();
|
||||
isClosed = true;
|
||||
mInput.close();
|
||||
mOutput.close();
|
||||
mTransport.close();
|
||||
mClosed = true;
|
||||
} catch (Exception e) {
|
||||
}
|
||||
client = null;
|
||||
input = null;
|
||||
output = null;
|
||||
listener = null;
|
||||
mTransport = null;
|
||||
mInput = null;
|
||||
mOutput = null;
|
||||
mListener = null;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -727,196 +691,4 @@ public class ServerSession implements Runnable, ObexSession {
|
||||
return ResponseCodes.OBEX_HTTP_INTERNAL_ERROR;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the server received an authentication challenge header. This
|
||||
* will cause the authenticator to handle the authentication challenge.
|
||||
*
|
||||
* @param header
|
||||
* the header with the authentication challenge
|
||||
*
|
||||
* @return <code>true</code> if the last request should be resent;
|
||||
* <code>false</code> if the last request should not be resent
|
||||
*/
|
||||
protected boolean handleAuthChall(HeaderSet header) {
|
||||
if (authenticator == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* An authentication challenge is made up of one required and two
|
||||
* optional tag length value triplets. The tag 0x00 is required to be in
|
||||
* the authentication challenge and it represents the challenge digest
|
||||
* that was received. The tag 0x01 is the options tag. This tag tracks
|
||||
* if user ID is required and if full access will be granted. The tag
|
||||
* 0x02 is the realm, which provides a description of which user name
|
||||
* and password to use.
|
||||
*/
|
||||
byte[] challenge = ObexHelper.getTagValue((byte)0x00, header.authChall);
|
||||
byte[] option = ObexHelper.getTagValue((byte)0x01, header.authChall);
|
||||
byte[] description = ObexHelper.getTagValue((byte)0x02, header.authChall);
|
||||
|
||||
String realm = "";
|
||||
if (description != null) {
|
||||
byte[] realmString = new byte[description.length - 1];
|
||||
System.arraycopy(description, 1, realmString, 0, realmString.length);
|
||||
|
||||
switch (description[0] & 0xFF) {
|
||||
|
||||
case 0x00:
|
||||
// ASCII encoding
|
||||
// Fall through
|
||||
case 0x01:
|
||||
// ISO-8859-1 encoding
|
||||
try {
|
||||
realm = new String(realmString, "ISO8859_1");
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("Unsupported Encoding Scheme");
|
||||
}
|
||||
break;
|
||||
|
||||
case 0xFF:
|
||||
// UNICODE Encoding
|
||||
realm = ObexHelper.convertToUnicode(realmString, false);
|
||||
break;
|
||||
|
||||
case 0x02:
|
||||
// ISO-8859-2 encoding
|
||||
// Fall through
|
||||
case 0x03:
|
||||
// ISO-8859-3 encoding
|
||||
// Fall through
|
||||
case 0x04:
|
||||
// ISO-8859-4 encoding
|
||||
// Fall through
|
||||
case 0x05:
|
||||
// ISO-8859-5 encoding
|
||||
// Fall through
|
||||
case 0x06:
|
||||
// ISO-8859-6 encoding
|
||||
// Fall through
|
||||
case 0x07:
|
||||
// ISO-8859-7 encoding
|
||||
// Fall through
|
||||
case 0x08:
|
||||
// ISO-8859-8 encoding
|
||||
// Fall through
|
||||
case 0x09:
|
||||
// ISO-8859-9 encoding
|
||||
// Fall through
|
||||
default:
|
||||
throw new RuntimeException("Unsupported Encoding Scheme");
|
||||
}
|
||||
}
|
||||
|
||||
boolean isUserIDRequired = false;
|
||||
boolean isFullAccess = true;
|
||||
if (option != null) {
|
||||
if ((option[0] & 0x01) != 0) {
|
||||
isUserIDRequired = true;
|
||||
}
|
||||
|
||||
if ((option[0] & 0x02) != 0) {
|
||||
isFullAccess = false;
|
||||
}
|
||||
}
|
||||
|
||||
PasswordAuthentication result = null;
|
||||
header.authChall = null;
|
||||
|
||||
try {
|
||||
result = authenticator.onAuthenticationChallenge(realm, isUserIDRequired, isFullAccess);
|
||||
} catch (Exception e) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* If no password is provided then we not resent the request
|
||||
*/
|
||||
if (result == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
byte[] password = result.getPassword();
|
||||
if (password == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
byte[] userName = result.getUserName();
|
||||
|
||||
/*
|
||||
* Create the authentication response header. It includes 1 required and
|
||||
* 2 option tag length value triples. The required triple has a tag of
|
||||
* 0x00 and is the response digest. The first optional tag is 0x01 and
|
||||
* represents the user ID. If no user ID is provided, then no user ID
|
||||
* will be sent. The second optional tag is 0x02 and is the challenge
|
||||
* that was received. This will always be sent
|
||||
*/
|
||||
if (userName != null) {
|
||||
header.authResp = new byte[38 + userName.length];
|
||||
header.authResp[36] = (byte)0x01;
|
||||
header.authResp[37] = (byte)userName.length;
|
||||
System.arraycopy(userName, 0, header.authResp, 38, userName.length);
|
||||
} else {
|
||||
header.authResp = new byte[36];
|
||||
}
|
||||
|
||||
// Create the secret String
|
||||
byte[] digest = new byte[challenge.length + password.length + 1];
|
||||
System.arraycopy(challenge, 0, digest, 0, challenge.length);
|
||||
// Insert colon between challenge and password
|
||||
digest[challenge.length] = (byte)0x3A;
|
||||
System.arraycopy(password, 0, digest, challenge.length + 1, password.length);
|
||||
|
||||
// Add the Response Digest
|
||||
header.authResp[0] = (byte)0x00;
|
||||
header.authResp[1] = (byte)0x10;
|
||||
|
||||
System.arraycopy(ObexHelper.computeMd5Hash(digest), 0, header.authResp, 2, 16);
|
||||
|
||||
// Add the challenge
|
||||
header.authResp[18] = (byte)0x02;
|
||||
header.authResp[19] = (byte)0x10;
|
||||
System.arraycopy(challenge, 0, header.authResp, 20, 16);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the server received an authentication response header. This
|
||||
* will cause the authenticator to handle the authentication response.
|
||||
*
|
||||
* @param authResp
|
||||
* the authentication response
|
||||
*
|
||||
* @return <code>true</code> if the response passed; <code>false</code> if
|
||||
* the response failed
|
||||
*/
|
||||
protected boolean handleAuthResp(byte[] authResp) {
|
||||
if (authenticator == null) {
|
||||
return false;
|
||||
}
|
||||
// get the correct password from the application
|
||||
byte[] correctPassword = authenticator.onAuthenticationResponse(ObexHelper.getTagValue(
|
||||
(byte)0x01, authResp));
|
||||
if (correctPassword == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
byte[] temp = new byte[correctPassword.length + 16];
|
||||
|
||||
System.arraycopy(challengeDigest, 0, temp, 0, 16);
|
||||
System.arraycopy(correctPassword, 0, temp, 16, correctPassword.length);
|
||||
|
||||
byte[] correctResponse = ObexHelper.computeMd5Hash(temp);
|
||||
byte[] actualResponse = ObexHelper.getTagValue((byte)0x00, authResp);
|
||||
|
||||
// compare the MD5 hash array .
|
||||
for (int i = 0; i < 16; i++) {
|
||||
if (correctResponse[i] != actualResponse[i]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -61,7 +61,7 @@ public interface SessionNotifier {
|
||||
* does not have a <code>ServiceRecord</code> in the SDDB, the
|
||||
* <code>ServiceRecord</code> for this object will be added to the SDDB.
|
||||
* This method requests the BCC to put the
|
||||
* local device in connectable mode so that it will respond to
|
||||
* local device in connectible mode so that it will respond to
|
||||
* connection attempts by clients.
|
||||
* <P>
|
||||
* The following checks are done to verify that the service record
|
||||
@@ -101,10 +101,10 @@ public interface SessionNotifier {
|
||||
* be due to insufficient disk space, database locks, etc.
|
||||
*
|
||||
* @throws BluetoothStateException if the server device could
|
||||
* not be placed in connectable mode because the device user has
|
||||
* configured the device to be non-connectable
|
||||
* not be placed in connectible mode because the device user has
|
||||
* configured the device to be non-connectible
|
||||
*/
|
||||
public ObexSession acceptAndOpen(ServerRequestHandler handler) throws IOException;
|
||||
ObexSession acceptAndOpen(ServerRequestHandler handler) throws IOException;
|
||||
|
||||
/**
|
||||
* Waits for a transport layer connection to be established and specifies
|
||||
@@ -117,7 +117,7 @@ public interface SessionNotifier {
|
||||
* does not have a <code>ServiceRecord</code> in the SDDB, the
|
||||
* <code>ServiceRecord</code> for this object will be added to the SDDB.
|
||||
* This method requests the BCC to put the
|
||||
* local device in connectable mode so that it will respond to
|
||||
* local device in connectible mode so that it will respond to
|
||||
* connection attempts by clients.
|
||||
* <P>
|
||||
* The following checks are done to verify that the service record
|
||||
@@ -160,9 +160,8 @@ public interface SessionNotifier {
|
||||
* be due to insufficient disk space, database locks, etc.
|
||||
*
|
||||
* @throws BluetoothStateException if the server device could
|
||||
* not be placed in connectable mode because the device user has
|
||||
* configured the device to be non-connectable
|
||||
* not be placed in connectible mode because the device user has
|
||||
* configured the device to be non-connectible
|
||||
*/
|
||||
public ObexSession acceptAndOpen(ServerRequestHandler handler, Authenticator auth)
|
||||
throws IOException;
|
||||
ObexSession acceptAndOpen(ServerRequestHandler handler, Authenticator auth) throws IOException;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user