Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
com.intel.bluetooth.obex.OBEXServerSessionImpl Maven / Gradle / Ivy
/**
* BlueCove - Java library for Bluetooth
* Copyright (C) 2007-2008 Vlad Skarzhevskyy
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* @version $Id: OBEXServerSessionImpl.java 2322 2008-07-04 03:14:54Z skarzhevskyy $
*/
package com.intel.bluetooth.obex;
import java.io.EOFException;
import java.io.IOException;
import javax.microedition.io.StreamConnection;
import javax.obex.Authenticator;
import javax.obex.HeaderSet;
import javax.obex.ResponseCodes;
import javax.obex.ServerRequestHandler;
import com.intel.bluetooth.BlueCoveImpl;
import com.intel.bluetooth.BluetoothServerConnection;
import com.intel.bluetooth.DebugLog;
import com.intel.bluetooth.UtilsJavaSE;
class OBEXServerSessionImpl extends OBEXSessionBase implements Runnable, BluetoothServerConnection {
private ServerRequestHandler handler;
private boolean isConnected = false;
private OBEXServerOperation operation;
private boolean closeRequested = false;
private volatile boolean delayClose = false;
private Object canCloseEvent = new Object();
private Object stackID;
private static int threadNumber;
private static synchronized int nextThreadNum() {
return threadNumber++;
}
OBEXServerSessionImpl(StreamConnection connection, ServerRequestHandler handler, Authenticator authenticator,
OBEXConnectionParams obexConnectionParams) throws IOException {
super(connection, obexConnectionParams);
this.handler = handler;
this.authenticator = authenticator;
stackID = BlueCoveImpl.getCurrentThreadBluetoothStackID();
Thread t = new Thread(this, "OBEXServerSessionThread-" + nextThreadNum());
UtilsJavaSE.threadSetDaemon(t);
t.start();
}
public void run() {
try {
if (stackID != null) {
BlueCoveImpl.setThreadBluetoothStackID(stackID);
}
while (!isClosed() && !closeRequested) {
if (!handleRequest()) {
return;
}
}
} catch (Throwable e) {
if (this.isConnected) {
DebugLog.error("OBEXServerSession error", e);
}
} finally {
DebugLog.debug("OBEXServerSession ends");
try {
super.close();
} catch (IOException e) {
DebugLog.debug("OBEXServerSession close error", e);
}
}
}
public void close() throws IOException {
closeRequested = true;
while (delayClose) {
synchronized (canCloseEvent) {
try {
if (delayClose) {
canCloseEvent.wait(700);
}
} catch (InterruptedException e) {
}
delayClose = false;
}
}
if (!isClosed()) {
DebugLog.debug("OBEXServerSession close");
// (new Throwable()).printStackTrace();
if (operation != null) {
operation.close();
operation = null;
}
}
super.close();
}
private boolean handleRequest() throws IOException {
DebugLog.debug("OBEXServerSession handleRequest");
delayClose = false;
byte[] b;
try {
b = readOperation();
} catch (EOFException e) {
if (isConnected) {
throw e;
}
DebugLog.debug("OBEXServerSession got EOF");
close();
return false;
}
delayClose = true;
try {
int opcode = b[0] & 0xFF;
boolean finalPacket = ((opcode & OBEXOperationCodes.FINAL_BIT) != 0);
if (finalPacket) {
DebugLog.debug("OBEXServerSession got operation finalPacket");
}
switch (opcode) {
case OBEXOperationCodes.CONNECT:
processConnect(b);
break;
case OBEXOperationCodes.DISCONNECT:
processDisconnect(b);
break;
case OBEXOperationCodes.PUT_FINAL:
case OBEXOperationCodes.PUT:
processPut(b, finalPacket);
break;
case OBEXOperationCodes.SETPATH | OBEXOperationCodes.FINAL_BIT:
case OBEXOperationCodes.SETPATH:
processSetPath(b, finalPacket);
break;
case OBEXOperationCodes.ABORT:
processAbort();
break;
case OBEXOperationCodes.GET_FINAL:
case OBEXOperationCodes.GET:
processGet(b, finalPacket);
break;
default:
writeOperation(ResponseCodes.OBEX_HTTP_NOT_IMPLEMENTED, null);
}
} finally {
delayClose = false;
}
synchronized (canCloseEvent) {
canCloseEvent.notifyAll();
}
return true;
}
private void processConnect(byte[] b) throws IOException {
DebugLog.debug("Connect operation");
if (b[3] != OBEXOperationCodes.OBEX_VERSION) {
throw new IOException("Unsupported client OBEX version " + b[3]);
}
if (b.length < 7) {
throw new IOException("Corrupted OBEX data");
}
int requestedMTU = OBEXUtils.bytesToShort(b[5], b[6]);
if (requestedMTU < OBEXOperationCodes.OBEX_MINIMUM_MTU) {
throw new IOException("Invalid MTU " + requestedMTU);
}
this.mtu = requestedMTU;
DebugLog.debug("mtu selected", this.mtu);
OBEXHeaderSetImpl requestHeaders = OBEXHeaderSetImpl.readHeaders(b, 7);
handleAuthenticationResponse(requestHeaders, handler);
HeaderSet replyHeaders = createOBEXHeaderSet();
handleAuthenticationChallenge(requestHeaders, (OBEXHeaderSetImpl) replyHeaders);
int rc = ResponseCodes.OBEX_HTTP_INTERNAL_ERROR;
try {
rc = handler.onConnect(requestHeaders, replyHeaders);
} catch (Throwable e) {
DebugLog.error("onConnect", e);
}
byte[] connectResponse = new byte[4];
connectResponse[0] = OBEXOperationCodes.OBEX_VERSION;
connectResponse[1] = 0; /* Flags */
connectResponse[2] = OBEXUtils.hiByte(obexConnectionParams.mtu);
connectResponse[3] = OBEXUtils.loByte(obexConnectionParams.mtu);
writeOperation(rc, connectResponse, OBEXHeaderSetImpl.toByteArray(replyHeaders));
if (rc == ResponseCodes.OBEX_HTTP_OK) {
this.isConnected = true;
}
}
private boolean validateConnection() throws IOException {
if (this.isConnected) {
return true;
}
writeOperation(ResponseCodes.OBEX_HTTP_BAD_REQUEST, null);
return false;
}
private void processDisconnect(byte[] b) throws IOException {
DebugLog.debug("Disconnect operation");
if (!validateConnection()) {
return;
}
HeaderSet requestHeaders = OBEXHeaderSetImpl.readHeaders(b, 3);
HeaderSet replyHeaders = createOBEXHeaderSet();
int rc = ResponseCodes.OBEX_HTTP_OK;
try {
handler.onDisconnect(requestHeaders, replyHeaders);
} catch (Throwable e) {
rc = ResponseCodes.OBEX_HTTP_UNAVAILABLE;
DebugLog.error("onDisconnect", e);
}
this.isConnected = false;
writeOperation(rc, OBEXHeaderSetImpl.toByteArray(replyHeaders));
}
private void processDelete(HeaderSet requestHeaders) throws IOException {
DebugLog.debug("Delete operation");
HeaderSet replyHeaders = createOBEXHeaderSet();
int rc = ResponseCodes.OBEX_HTTP_OK;
try {
rc = handler.onDelete(requestHeaders, replyHeaders);
} catch (Throwable e) {
rc = ResponseCodes.OBEX_HTTP_UNAVAILABLE;
DebugLog.error("onDelete", e);
}
writeOperation(rc, OBEXHeaderSetImpl.toByteArray(replyHeaders));
}
private void processPut(byte[] b, boolean finalPacket) throws IOException {
DebugLog.debug("Put operation");
if (!validateConnection()) {
return;
}
HeaderSet requestHeaders = OBEXHeaderSetImpl.readHeaders(b, 3);
operation = new OBEXServerOperationPut(this, requestHeaders, finalPacket);
while ((!finalPacket) && (!operation.isIncommingDataReceived())) {
finalPacket = operation.exchangeRequestPhasePackets();
}
if (operation.isErrorReceived()) {
return;
}
// A PUT operation with NO Body or End-of-Body headers whatsoever should
// be treated as a delete request.
if (finalPacket && (!operation.isIncommingDataReceived())) {
processDelete(operation.getReceivedHeaders());
return;
}
try {
int rc = ResponseCodes.OBEX_HTTP_OK;
try {
rc = handler.onPut(operation);
} catch (Throwable e) {
rc = ResponseCodes.OBEX_HTTP_UNAVAILABLE;
DebugLog.error("onPut", e);
}
operation.writeResponse(rc);
} finally {
operation.close();
operation = null;
}
}
private void processGet(byte[] b, boolean finalPacket) throws IOException {
DebugLog.debug("Get operation");
if (!validateConnection()) {
return;
}
HeaderSet requestHeaders = OBEXHeaderSetImpl.readHeaders(b, 3);
operation = new OBEXServerOperationGet(this, requestHeaders, finalPacket);
while ((!finalPacket) && (!operation.isIncommingDataReceived())) {
finalPacket = operation.exchangeRequestPhasePackets();
}
if (operation.isErrorReceived()) {
return;
}
try {
int rc = ResponseCodes.OBEX_HTTP_OK;
try {
rc = handler.onGet(operation);
} catch (Throwable e) {
rc = ResponseCodes.OBEX_HTTP_UNAVAILABLE;
DebugLog.error("onGet", e);
}
operation.writeResponse(rc);
} finally {
operation.close();
operation = null;
}
}
private void processAbort() throws IOException {
DebugLog.debug("Abort operation");
if (!validateConnection()) {
return;
}
if (operation != null) {
operation.close();
operation = null;
}
writeOperation(OBEXOperationCodes.OBEX_RESPONSE_SUCCESS, null);
}
private void processSetPath(byte[] b, boolean finalPacket) throws IOException {
DebugLog.debug("SetPath operation");
if (!validateConnection()) {
return;
}
if (b.length < 5) {
throw new IOException("Corrupted OBEX data");
}
HeaderSet requestHeaders = OBEXHeaderSetImpl.readHeaders(b, 5);
// DebugLog.debug("setPath b[3]", b[3]);
// b[4] = (byte) ((backup?1:0) | (create?0:2));
boolean backup = ((b[3] & 1) != 0);
boolean create = ((b[3] & 2) == 0);
DebugLog.debug("setPath backup", backup);
DebugLog.debug("setPath create", create);
HeaderSet replyHeaders = createOBEXHeaderSet();
int rc = ResponseCodes.OBEX_HTTP_OK;
try {
rc = handler.onSetPath(requestHeaders, replyHeaders, backup, create);
} catch (Throwable e) {
rc = ResponseCodes.OBEX_HTTP_UNAVAILABLE;
DebugLog.error("onSetPath", e);
}
writeOperation(rc, OBEXHeaderSetImpl.toByteArray(replyHeaders));
}
}