Methods Summary |
---|
void | brokenLink()Sets link broken flag.
close();
|
public void | close()
try {
if (transport != null) {
transport.close();
}
} catch (IOException e) {
// nothing
}
transport = null;
|
private final long | decodeInt()
return ((buffer[packetOffset+0]& 0xffl) << 24)
+ ((buffer[packetOffset+1]& 0xffl) << 16)
+ ((buffer[packetOffset+2]& 0xffl) << 8)
+ (buffer[packetOffset+3]& 0xffl);
|
final int | decodeLength16(int off)
return ((((int)buffer[off]) & 0xFF) << 8)
+ (((int)buffer[off + 1]) & 0xFF);
|
private final java.util.Calendar | decodeTime8601()
int year, month, date, hour, minute, second;
int len = decodeLength16(packetOffset) - 3;
packetOffset += 2;
if (len < 15 || len > 16
|| buffer[packetOffset + 8] != 0x54 // 'T'
|| (len == 16 && buffer[packetOffset + 15] != 0x5A)) { // 'Z'
packetOffset += len;
throw new IOException("corrupted time header");
}
for (int i = 0; i < 14; i++) {
if (i == 8) continue;
int chr = buffer[packetOffset + i] - 0x30; // '0'
if (chr < 0 || chr > 9) {
packetOffset += len;
throw new IOException("corrupted time header");
}
}
year = (buffer[packetOffset+0] - 0x30) * 1000
+ (buffer[packetOffset+1] - 0x30) * 100
+ (buffer[packetOffset+2] - 0x30) * 10
+ (buffer[packetOffset+3] - 0x30);
month = (buffer[packetOffset+4] - 0x30) * 10
+ (buffer[packetOffset+5] - 0x30);
date = (buffer[packetOffset+6] - 0x30) * 10
+ (buffer[packetOffset+7] - 0x30);
hour = (buffer[packetOffset+9] - 0x30) * 10
+ (buffer[packetOffset+10] - 0x30);
minute = (buffer[packetOffset+11] - 0x30) * 10
+ (buffer[packetOffset+12] - 0x30);
second = (buffer[packetOffset+13] - 0x30) * 10
+ (buffer[packetOffset+14] - 0x30);
// is check validness of time fields required?
Calendar cal;
// 'len' value 15 means local time,
// 16 means UTC (in this case time string has 'Z' suffix)
if (len == 16) {
cal = Calendar.getInstance(utcTimeZone);
} else {
cal = Calendar.getInstance();
}
cal.set(Calendar.YEAR, year);
cal.set(Calendar.MONTH, month - 1); // Calendar.JANUARY = 0
cal.set(Calendar.DATE, date);
// ISO 8601 standard uses the 24-hour clock
// Therefore you use HOUR_OF_DAY not HOUR
cal.set(Calendar.HOUR_OF_DAY, hour);
cal.set(Calendar.MINUTE, minute);
cal.set(Calendar.SECOND, second);
// set milliseconds to zero since
// ISO 8601 uses only second precision
cal.set(Calendar.MILLISECOND, 0);
packetOffset += len;
return cal;
|
private final void | encodeInt(long val)
buffer[packetLength++] = (byte)(val >> 24);
buffer[packetLength++] = (byte)(val >> 16);
buffer[packetLength++] = (byte)(val >> 8);
buffer[packetLength++] = (byte)val;
|
public abstract long | getConnectionID()
|
int | getPacketLength()
return packetLength;
|
public javax.microedition.io.Connection | getTransport()
if (transport == null) {
throw new IOException("connection error");
}
return transport.getUnderlyingConnection();
|
abstract void | headerTooLarge()This method is called to handle a situation than header is too large.
|
boolean | isClosed()
return transport == null;
|
abstract void | onAuthenticationFailure(byte[] username)Called when requested authentication failed.
Implemented on server to call handler.
|
void | onMissingAuthResponse()
|
void | packetAddAuthResponses()
try {
for (int i = 0; i < authResponses.size(); i++) {
if (DEBUG) {
System.out.println(
"packetAddAuthResponses(): added response");
}
ObexAuth response = (ObexAuth) authResponses.elementAt(i);
int len = response.replyAuthChallenge(buffer, packetLength,
authenticator);
packetLength += len;
}
} catch (ArrayIndexOutOfBoundsException e) {
throw new IOException("auth response request too large");
}
if (packetLength > maxSendLength) {
throw new IOException("auth response request too large");
}
|
final void | packetAddConnectionID(long id, HeaderSetImpl headers)Connection Identifier:
* must be first header in packet
* 0xFFFFFFFF considered invalid - it is up to application
* can't be sent on connect() request
* can't be used with Target header in one packet
// SPEC: Illegal to send a Connection Id and a Target header
// in the same operation.
if (headers != null
&& headers.getHeader(HeaderSetImpl.TARGET) != null) {
return;
}
if (id < 0L || id > 0xFFFFFFFFL) {
return;
}
buffer[packetLength++] = (byte)HEADER_CONNECTION_ID;
encodeInt(id);
|
int | packetAddData(byte[] data, int offset, int length)
if (DEBUG) {
System.out.println("packetAddData()");
}
// preventing writing several data blocks, just in case
if (dataClosed)
return 0;
if (!dataOpened) {
// let it be at least 3 bytes workload to create new Body header
if (packetLength + 6 > maxSendLength) {
return 0;
}
buffer[packetLength] = HEADER_BODY;
dataOffset = packetLength;
packetLength += 3;
dataOpened = true;
}
int len;
if (packetLength + length > maxSendLength) {
len = maxSendLength - packetLength;
} else {
len = length;
}
System.arraycopy(data, offset, buffer, packetLength, len);
packetLength += len;
return len;
|
final void | packetAddHeaders(HeaderSetImpl headers)Adds the specified headers to the packet.
if (DEBUG) {
System.out.println("packetAddHeaders()");
}
headerOverflow = false;
newHeader.sendAllQueued();
if (headers == null) {
return;
}
int[] idList = headers.getHeaderList();
if (!headers.challenges.isEmpty()) {
newHeader.sendOrQueue(HEADER_AUTH_CHALLENGE,
headers.challenges);
}
if (idList == null) {
return;
}
for (int i = 0; i < idList.length; i++) {
int id = idList[i];
Object value = headers.getHeader(id);
newHeader.sendOrQueue(id, value);
}
|
void | packetBegin(byte[] head)
if (DEBUG) {
System.out.println("packetBegin()");
}
containsTargetHeader = false;
moreHeaders = true;
challengesToSend = false;
System.arraycopy(head, 0, buffer, 0, head.length);
packetLength = head.length;
authChallenges.removeAllElements();
dataOpened = false;
dataClosed = false;
dataOffset = -3; // generate aoobe when accessed
|
boolean | packetEOFBody()
if (DEBUG) {
System.out.println("packetEOFBody()");
}
if (dataClosed) {
return false;
}
if (dataOpened) {
buffer[dataOffset+0] = HEADER_EOFBODY;
return true;
} else {
if (packetLength + 3 > maxSendLength) {
return false;
}
buffer[packetLength++] = HEADER_EOFBODY;
buffer[packetLength++] = 0; // length
buffer[packetLength++] = 3;
return true;
}
|
void | packetEnd()
if (DEBUG) {
System.out.println("packetEnd()");
}
moreHeaders = false;
if (transport == null) {
throw new IOException("connection error");
}
if (dataOpened) {
// closing Body header
int len = packetLength - dataOffset;
buffer[dataOffset+1] = (byte)(len >> 8);
buffer[dataOffset+2] = (byte)len;
dataOpened = false;
dataClosed = true;
}
// update packet length field
buffer[1] = (byte)(packetLength / 0x100);
buffer[2] = (byte)(packetLength % 0x100);
if (DEBUG) {
int len = packetLength;
if (!DEBUG2 && len > 20) {
len = 20;
}
System.out.println("send:");
for (int i = 0; i < len; i++) {
System.out.print(" 0x" + Integer.toHexString(buffer[i] & 0xFF));
int chr = buffer[i] & 0xFF;
if (chr >= 32 && chr < 128) {
System.out.print("(" + (char)(buffer[i] & 0xFF) + ")");
}
}
if (packetLength != len) {
System.out.print("...");
}
System.out.println("");
}
try {
transport.write(buffer, packetLength);
} catch (IOException e) {
brokenLink();
throw e;
}
|
void | packetEndStripConnID()Finish packet and send it. Remove Connection ID header if packet also
contains TARGET header.
// first header id is in 3 byte on all packet except CONNECT
// and this function is known not to be called for connect() operation.
if ((buffer[3] & 0xFF) == HeaderSetImpl.TARGET) {
packetLength -= 5;
// length of Connection ID packet is 5 bytes:
// 1 byte header + 4 byte int value
for (int i = 3; i < packetLength; i++) {
buffer[i] = buffer[i + 5];
}
}
packetEnd();
|
void | packetMarkFinal()
if (DEBUG) {
System.out.println("packetMarkFinal()");
}
buffer[0] |= 0x80;
|
private final void | parseConnectionID()
int headerId = buffer[packetOffset] & 0xFF;
// parse connection ID
if (packetOffset + 5 > packetLength
|| headerId != HEADER_CONNECTION_ID) {
return;
}
packetOffset++;
long id = decodeInt();
packetOffset += 4;
setConnectionID(id);
|
final void | parseEnd()
if (DEBUG) {
System.out.println("parseEnd()");
}
if (authFailed) {
authFailed = false;
onMissingAuthResponse();
}
|
private final void | parseHeader(HeaderSetImpl headers)
if (DEBUG) {
System.out.println("parseHeader()");
}
try {
int headerId = buffer[packetOffset++] & 0xff;
int inputType = headerId >> 6;
int outputType = HeaderSetImpl.internalType(headerId);
if (outputType != HeaderSetImpl.TYPE_UNSUPPORTED) {
inputType = outputType;
}
Object result = null;
switch (inputType) {
// ids which require special handling
case HeaderSetImpl.TYPE_SPECIAL_TIME_ISO:
try {
result = decodeTime8601();
} catch (IOException e) {
// IMPL_NOTE: Got invalid time header,
// should probably just ignore it.
}
break;
case HeaderSetImpl.TYPE_SPECIAL_TIME_4:
long date = decodeInt();
Calendar cal = Calendar.getInstance(utcTimeZone);
cal.setTime(new Date(date * 1000L));
result = cal;
packetOffset += 4;
break;
case HeaderSetImpl.TYPE_SPECIAL_TYPE:
int len = decodeLength16(packetOffset) - 3;
packetOffset += 2;
if (buffer[packetOffset + len - 1] != 0) {
throw new IOException(
"protocol error, "
+ "type field not null terminated");
}
result = new String(buffer, packetOffset, len - 1,
"ISO-8859-1");
packetOffset += len;
break;
// normal ids
case HeaderSetImpl.TYPE_LONG:
result = new Long(decodeInt());
packetOffset += 4;
break;
case HeaderSetImpl.TYPE_UNICODE:
len = decodeLength16(packetOffset) - 3;
packetOffset += 2;
if (len < 2 || buffer[packetOffset + len - 1] != 0
|| buffer[packetOffset + len - 2] != 0) {
throw new IOException("protocol error, " +
"unicode string is not null terminated");
}
result = new String(buffer,
packetOffset, len - 2, "UTF-16BE");
// result = new String(buffer, packetOffset, len,
// "ISO-8859-1");
packetOffset += len;
break;
case HeaderSetImpl.TYPE_BYTEARRAY:
len = decodeLength16(packetOffset) - 3;
packetOffset += 2;
result = new byte[len];
System.arraycopy(buffer, packetOffset, result, 0, len);
packetOffset += len;
break;
case HeaderSetImpl.TYPE_BYTE:
result = new Byte(buffer[packetOffset++]);
break;
case HeaderSetImpl.TYPE_AUTH_CHALLENGE:
len = decodeLength16(packetOffset);
ObexAuth response =
ObexAuth.parseAuthChallenge(buffer, packetOffset-1,
len);
if (response != null)
authResponses.addElement(response);
packetOffset += len - 1;
return;
case HeaderSetImpl.TYPE_AUTH_RESPONSE:
len = decodeLength16(packetOffset);
boolean good =
ObexAuth.checkAuthResponse(buffer, packetOffset-1, len,
this, authChallenges);
if (good) authFailed = false;
packetOffset += len - 1;
if (DEBUG) {
System.out.println("checkAuthResponse() = " + good);
}
return;
}
if (packetOffset > packetLength) {
throw new IOException("protocol error");
}
if (outputType != HeaderSetImpl.TYPE_UNSUPPORTED) {
headers.setHeader(headerId, result);
} else if (DEBUG) {
System.out.println("unsupported header id = 0x"
+ Integer.toHexString(headerId).toUpperCase());
}
} catch (ArrayIndexOutOfBoundsException e) {
throw new IOException("protocol error");
}
|
final int | parsePacketData(HeaderSetImpl headers, byte[] output, int outputOffset, int outputLength)Parse packet headers, put BODY field content (data) in specified output
array. If output is null, search for a BODY block and return 1 if it is
found.
if (DEBUG2) {
System.out.println("parsePacketData()");
}
int result = 0;
while (true) {
int len = packetOffset - dataOffset;
if (DEBUG2) {
System.out.print("packetOffset = "+packetOffset+
" dataOffset = " +dataOffset);
System.out.println(" len = " + len);
}
if (len > 0) {
if (output == null) {
// special case for serching first data block
// without actual read
return 1;
}
if (len > outputLength) len = outputLength;
System.arraycopy(buffer, dataOffset,
output, outputOffset, len);
outputOffset += len;
outputLength -= len;
dataOffset += len;
result += len;
if (outputLength == 0)
return result;
continue;
}
if (DEBUG) {
System.out.println("packetOffset = " + packetOffset
+" packetLength = " + packetLength);
}
if (packetOffset == packetLength) {
return result;
}
int headerId = buffer[packetOffset] & 0xff;
if (headerId == HEADER_BODY || headerId == HEADER_EOFBODY) {
isEof = (headerId == HEADER_EOFBODY);
dataOffset = packetOffset + 3;
int length = decodeLength16(packetOffset + 1);
if (packetOffset + length > packetLength) {
throw new IOException("protocol error");
}
packetOffset += length;
continue;
}
parseHeader(headers);
dataOffset = packetOffset;
}
|
final void | parsePacketDataBegin(HeaderSetImpl headers, int offset)Begin parsing packet headers in packet possibly containing BODY
(data fields).
if (DEBUG) {
System.out.println("parsePacketDataBegin()");
}
packetOffset = offset;
headers.packetType = buffer[0] & 0xFF;
parseConnectionID();
dataOffset = packetOffset;
|
final void | parsePacketHeaders(HeaderSetImpl headers, int offset)Parser all packet headers, BODY headers should not apear
and silently ignored.
if (DEBUG) {
System.out.println("parsePacketHeaders()");
}
packetOffset = offset;
headers.packetType = buffer[0] & 0xFF;
parseConnectionID();
while (packetOffset != packetLength) {
parseHeader(headers);
}
parseEnd();
|
private int | readLeast(int offset, int length)Reads at least length bytes starting from the given offset
into the internal buffer. More than length bytes may be
actually read. The calling function must ensure the buffer is large
enough to store the entire packet.
if (transport == null) {
throw new IOException("connection error");
}
int read = 0;
while (read < length) {
int count = transport.read(cache);
System.arraycopy(cache, 0, buffer, offset + read, count);
read += count;
if (read < length) {
try {
Thread.sleep(TRANSPORT_READ_INTERVAL);
} catch (InterruptedException e) {
throw new InterruptedIOException(e.getMessage());
}
}
}
return read;
|
final void | recvPacket()
authResponses.removeAllElements();
if (transport == null) {
throw new IOException("connection error");
}
try {
int read = readLeast(0, 3);
packetType = buffer[0] & 0xff;
packetLength = ((buffer[1] & 0xff) << 8) + (buffer[2] & 0xff);
if (DEBUG) {
Logging.report(Logging.INFORMATION, 0,
"Expecting " + packetLength + " bytes to arrive...");
}
if (read < packetLength) {
readLeast(read, packetLength - read);
}
// dump packet:
if (DEBUG) {
int len = packetLength;
if (!DEBUG2 && len > 20) {
len = 20;
}
System.out.println("recv: ");
for (int i = 0; i < len; i++) {
System.out.print(" 0x"
+ Integer.toHexString(buffer[i] & 0xFF)
.toUpperCase());
}
if (len != packetLength) System.out.print("...");
System.out.println("");
}
} catch (IOException e) {
brokenLink();
throw e;
}
|
void | restorePacketLength(int len)
packetLength = len;
|
final void | sendPacket(byte[] head, long connectionId, HeaderSetImpl headers, boolean allHeaders)
packetBegin(head);
packetAddConnectionID(connectionId, headers);
packetAddAuthResponses();
packetAddHeaders(headers);
if (allHeaders && !queuedHeaders.isEmpty()) {
queuedHeaders.removeAllElements();
throw new IOException("packet too large for peer");
}
packetEnd();
|
public void | setAuthenticator(javax.obex.Authenticator authenticator)
if (authenticator == null) {
throw new NullPointerException("null authenticator");
}
this.authenticator = authenticator;
|
public abstract void | setConnectionID(long id)
|
void | setPacketType(int type)
if (DEBUG) {
System.out.println("setPacketType()");
}
buffer[0] = (byte) type;
|
boolean | shouldSendAuthResponse()
return (packetType == ResponseCodes.OBEX_HTTP_UNAUTHORIZED)
&& (authResponses.size() != 0);
|
static int | validateStatus(int status)
switch (status) {
case ResponseCodes.OBEX_DATABASE_FULL:
case ResponseCodes.OBEX_DATABASE_LOCKED:
case ResponseCodes.OBEX_HTTP_ACCEPTED:
case ResponseCodes.OBEX_HTTP_BAD_GATEWAY:
case ResponseCodes.OBEX_HTTP_BAD_METHOD:
case ResponseCodes.OBEX_HTTP_BAD_REQUEST:
case ResponseCodes.OBEX_HTTP_CONFLICT:
case ResponseCodes.OBEX_HTTP_CREATED:
case ResponseCodes.OBEX_HTTP_ENTITY_TOO_LARGE:
case ResponseCodes.OBEX_HTTP_FORBIDDEN:
case ResponseCodes.OBEX_HTTP_GATEWAY_TIMEOUT:
case ResponseCodes.OBEX_HTTP_GONE:
case ResponseCodes.OBEX_HTTP_INTERNAL_ERROR:
case ResponseCodes.OBEX_HTTP_LENGTH_REQUIRED:
case ResponseCodes.OBEX_HTTP_MOVED_PERM:
case ResponseCodes.OBEX_HTTP_MOVED_TEMP:
case ResponseCodes.OBEX_HTTP_MULT_CHOICE:
case ResponseCodes.OBEX_HTTP_NO_CONTENT:
case ResponseCodes.OBEX_HTTP_NOT_ACCEPTABLE:
case ResponseCodes.OBEX_HTTP_NOT_AUTHORITATIVE:
case ResponseCodes.OBEX_HTTP_NOT_FOUND:
case ResponseCodes.OBEX_HTTP_NOT_IMPLEMENTED:
case ResponseCodes.OBEX_HTTP_NOT_MODIFIED:
case ResponseCodes.OBEX_HTTP_OK:
case ResponseCodes.OBEX_HTTP_PARTIAL:
case ResponseCodes.OBEX_HTTP_PAYMENT_REQUIRED:
case ResponseCodes.OBEX_HTTP_PRECON_FAILED:
case ResponseCodes.OBEX_HTTP_PROXY_AUTH:
case ResponseCodes.OBEX_HTTP_REQ_TOO_LARGE:
case ResponseCodes.OBEX_HTTP_RESET:
case ResponseCodes.OBEX_HTTP_SEE_OTHER:
case ResponseCodes.OBEX_HTTP_TIMEOUT:
case ResponseCodes.OBEX_HTTP_UNAUTHORIZED:
case ResponseCodes.OBEX_HTTP_UNAVAILABLE:
case ResponseCodes.OBEX_HTTP_UNSUPPORTED_TYPE:
case ResponseCodes.OBEX_HTTP_USE_PROXY:
case ResponseCodes.OBEX_HTTP_VERSION:
return status;
default:
return ResponseCodes.OBEX_HTTP_INTERNAL_ERROR;
}
|