blob: 2d2e2add31955724a185b8d930554bda78561f3f [file] [log] [blame]
/*
* This file is part of the QuickServer library
* Copyright (C) QuickServer.org
*
* Use, modification, copying and distribution of this software is subject to
* the terms and conditions of the GNU Lesser General Public License.
* You should have received a copy of the GNU LGP License along with this
* library; if not, you can download a copy from <http://www.quickserver.org/>.
*
* For questions, suggestions, bug-reports, enhancement-requests etc.
* visit http://www.quickserver.org
*
*/
package org.quickserver.net.server.impl;
import org.quickserver.net.server.*;
import org.quickserver.net.*;
import org.quickserver.util.*;
import java.io.*;
import java.net.*;
import java.util.logging.*;
import java.nio.channels.*;
public class BlockingClientHandler extends BasicClientHandler {
private static final Logger logger = Logger.getLogger(BlockingClientHandler.class.getName());
public BlockingClientHandler(int instanceCount) {
super(instanceCount);
}
public BlockingClientHandler() {
super();
}
public void clean() {
logger.log(Level.FINEST, "Starting clean - {0}", getName());
super.clean();
logger.log(Level.FINEST, "Finished clean - {0}", getName());
}
public void handleClient(TheClient theClient) throws Exception {
super.handleClient(theClient);
}
protected void setInputStream(InputStream in) throws IOException {
this.in = in;
if(getDataMode(DataType.IN) == DataMode.STRING) {
b_in = null;
o_in = null;
bufferedReader = new BufferedReader(new InputStreamReader(this.in, charset));
} else if(getDataMode(DataType.IN) == DataMode.OBJECT) {
b_in = null;
bufferedReader = null;
o_in = new ObjectInputStream(in);
} else if(getDataMode(DataType.IN) == DataMode.BYTE ||
getDataMode(DataType.IN) == DataMode.BINARY) {
o_in = null;
bufferedReader = null;
b_in = new BufferedInputStream(in);
}
}
public BufferedReader getBufferedReader() {
return bufferedReader;
}
public synchronized void closeConnection() {
if(connection==false) return;
connection = false;
try {
if(hasEvent(ClientEvent.MAX_CON_BLOCKING)==false) {
notifyCloseOrLost();
}
if(out!=null) {
logger.finest("Closing output streams");
try {
out.flush();
} catch(IOException ioe) {
logger.log(Level.FINEST, "Flushing output streams failed: "+ioe, ioe);
}
if(socket!=null && isSecure()==false) {
socket.shutdownOutput();
}
if(dataModeOUT == DataMode.OBJECT) {
o_out.close();
} else {
b_out.close();
}
if(out!=null) out.close();
}
if(in!=null) {
logger.finest("Closing input streams");
//if(socket!=null) socket.shutdownInput();
if(dataModeIN == DataMode.STRING) {
if(bufferedReader!=null) bufferedReader.close();
} else if(dataModeIN == DataMode.OBJECT) {
o_in.close();
} else {
b_in.close();
}
if(in!=null) in.close();
}
} catch(IOException e) {
logger.log(Level.WARNING, "Error in closeConnection: {0}", e);
if(logger.isLoggable(Level.FINE)) {
logger.log(Level.FINE, "StackTrace: "+e, e);
}
} catch(NullPointerException npe) {
logger.log(Level.FINE, "NullPointerException: "+npe, npe);
}
}
public void run() {
if(unprocessedClientEvents.isEmpty()) {
logger.finest("No unprocessed ClientEvents!");
return;
}
ClientEvent currentEvent = (ClientEvent) unprocessedClientEvents.poll();
if(currentEvent==null) {
threadEvent.set(null);
logger.finest("No unprocessed ClientEvents! pool was null");
return;
}
if(logger.isLoggable(Level.FINEST)) {
StringBuilder sb = new StringBuilder();
sb.append("Running ").append(getName());
sb.append(" using ");
sb.append(Thread.currentThread().getName());
sb.append(" for ");
synchronized(clientEvents) {
if(clientEvents.size()>1) {
sb.append(currentEvent).append(", Current Events - ").append(clientEvents);
} else {
sb.append(currentEvent);
}
}
logger.finest(sb.toString());
}
threadEvent.set(currentEvent);
try {
if(socket==null)
throw new SocketException("Socket was null!");
prepareForRun();
if(getThreadEvent()==ClientEvent.MAX_CON_BLOCKING) {
processMaxConnection(currentEvent);
}
try {
if(getThreadEvent()==ClientEvent.RUN_BLOCKING) {
clientEventHandler.gotConnected(this);
if(authorised == false) {
if(clientAuthenticationHandler==null && authenticator == null) {
authorised = true;
} else {
if(clientAuthenticationHandler!=null) {
AuthStatus authStatus = null;
do {
authStatus = processAuthorisation();
} while(authStatus==AuthStatus.FAILURE);
if(authStatus==AuthStatus.SUCCESS)
authorised = true;
} else {
processAuthorisation();
}
}
}//end of authorised
processRead();
}
} catch(SocketException e) {
appLogger.log(Level.FINEST, "SocketException - Client [{0}]: {1}",
new Object[]{getHostAddress(), e});
lost = true;
} catch(AppException e) {
appLogger.log(Level.FINEST, "AppException {0}: {1}", new Object[]{
Thread.currentThread().getName(), e});
} catch(javax.net.ssl.SSLException e) {
lost = true;
if(Assertion.isEnabled()) {
appLogger.log(Level.INFO, "SSLException - Client [{0}] {1}: {2}",
new Object[]{getHostAddress(), Thread.currentThread().getName(), e});
} else {
appLogger.log(Level.WARNING, "SSLException - Client [{0}]: {1}",
new Object[]{getHostAddress(), e});
}
} catch(ConnectionLostException e) {
lost = true;
if(e.getMessage()!=null)
appLogger.log(Level.FINEST, "Connection lost {0}: {1}",
new Object[]{Thread.currentThread().getName(), e});
else
appLogger.log(Level.FINEST, "Connection lost {0}", Thread.currentThread().getName());
} catch(IOException e) {
lost = true;
appLogger.log(Level.FINE, "IOError {0}: {1}", new Object[]{Thread.currentThread().getName(), e});
} catch(AssertionError er) {
logger.log(Level.WARNING, "[AssertionError] {0} {1}", new Object[]{getName(), er});
if(logger.isLoggable(Level.FINEST)) {
logger.log(Level.FINEST, "StackTrace {0}: {1}", new Object[]{
Thread.currentThread().getName(), MyString.getStackTrace(er)});
}
assertionSystemExit();
} catch(RuntimeException re) {
logger.log(Level.WARNING, "[RuntimeException] {0}", MyString.getStackTrace(re));
if(Assertion.isEnabled()) {
assertionSystemExit();
}
lost = true;
} catch(Throwable er) {
logger.log(Level.WARNING, "[Error] {0}", er);
if(logger.isLoggable(Level.FINEST)) {
logger.log(Level.FINEST, "StackTrace {0}: {1}",
new Object[]{Thread.currentThread().getName(), MyString.getStackTrace(er)});
}
if(Assertion.isEnabled()) {
assertionSystemExit();
}
lost = true;
}
if(getThreadEvent()!=ClientEvent.MAX_CON_BLOCKING) {
notifyCloseOrLost();
}
if(connection) {
logger.log(Level.FINEST, "{0} calling closeConnection()", Thread.currentThread().getName());
closeConnection();
}
} catch(javax.net.ssl.SSLException se) {
logger.log(Level.WARNING, "SSLException {0}", se);
} catch(IOException ie) {
logger.log(Level.WARNING, "IOError - Closing Client: {0}", ie);
} catch(RuntimeException re) {
logger.log(Level.WARNING, "[RuntimeException] {0} {1}", new Object[]{
getName(), MyString.getStackTrace(re)});
if(Assertion.isEnabled()) {
assertionSystemExit();
}
} catch(Exception e) {
logger.log(Level.WARNING, "Error on Event:{0} - Socket:{1} : {2}", new Object[]{getThreadEvent(), socket, e});
logger.log(Level.FINE, "StackTrace: {0}\n{1}", new Object[]{getName(), MyString.getStackTrace(e)});
if(Assertion.isEnabled()) {
assertionSystemExit();
}
} catch(Throwable e) {
logger.log(Level.WARNING, "Error on - Event:{0} - Socket:{1} : {2}", new Object[]{getThreadEvent(), socket, e});
logger.log(Level.FINE, "StackTrace: {0}\n{1}", new Object[]{getName(), MyString.getStackTrace(e)});
if(Assertion.isEnabled()) {
assertionSystemExit();
}
}
try {
if(socket!=null && socket.isClosed()==false) {
logger.finest("Closing Socket");
socket.close();
}
} catch(Exception re) {
logger.log(Level.WARNING, "Error closing Socket/Channel: {0}", re);
}
willClean = true;
returnClientData();
boolean returnClientHandler = false;
synchronized(lockObj) {
returnClientHandler = checkReturnClientHandler();
}
if(returnClientHandler) {
returnClientHandler(); //return to pool
}
}
protected boolean checkReturnClientHandler() {
return true;
}
private void processRead() throws IOException, ClassNotFoundException, AppException {
AuthStatus authStatus = null;
String rec = null;
Object recObject = null; //v1.2
byte[] recByte = null; //1.4
while(connection) {
try {
if(dataModeIN == DataMode.STRING) {
rec = bufferedReader.readLine();
if(rec==null) {
lost = true;
break;
}
if(getCommunicationLogging() && authorised == true) {
appLogger.log(Level.FINE, "Got STRING [{0}] : {1}",
new Object[]{getHostAddress(), rec});
}
totalReadBytes = totalReadBytes + rec.length() + 2;
if(authorised == false)
authStatus = clientAuthenticationHandler.handleAuthentication(this, rec);
else
clientCommandHandler.handleCommand(this, rec);
} else if(dataModeIN == DataMode.OBJECT) {
recObject = o_in.readObject();
if(recObject==null) {
lost = true;
break;
}
if(getCommunicationLogging() && authorised == true) {
appLogger.log(Level.FINE, "Got OBJECT [{0}] : {1}",
new Object[]{getHostAddress(), recObject.toString()});
}
totalReadBytes = totalReadBytes + 1;
if(authorised == false)
authStatus = clientAuthenticationHandler.handleAuthentication(this, recObject);
else
clientObjectHandler.handleObject(this, recObject);
} else if(dataModeIN == DataMode.BYTE) {
rec = readBytes();
if(rec==null) {
lost = true;
break;
}
if(getCommunicationLogging() && authorised == true) {
appLogger.log(Level.FINE, "Got BYTE [{0}] : {1}", new Object[]{getHostAddress(), rec});
}
totalReadBytes = totalReadBytes + rec.length();
if(authorised == false)
authStatus = clientAuthenticationHandler.handleAuthentication(this, rec);
else
clientCommandHandler.handleCommand(this, rec);
} else if(dataModeIN == DataMode.BINARY) {
recByte = readBinary();
if(recByte==null) {
lost = true;
break;
}
if(getCommunicationLogging() && authorised == true) {
if(getServer().isRawCommunicationLogging()) {
if(getServer().getRawCommunicationMaxLength()>0 &&
recByte.length>getServer().getRawCommunicationMaxLength()) {
appLogger.log(Level.FINE,
"Got BINARY [{0}] : {1}; RAW: {2}{3}", new Object[]{
getHostAddress(), MyString.getMemInfo(recByte.length),
new String(recByte,0,getServer().getRawCommunicationMaxLength(),charset),"..."});
} else {
appLogger.log(Level.FINE,
"Got BINARY [{0}] : {1}; RAW: {2}", new Object[]{
getHostAddress(), MyString.getMemInfo(recByte.length),
new String(recByte,charset)});
}
} else {
appLogger.log(Level.FINE,
"Got BINARY [{0}] : {1}", new Object[]{getHostAddress(),
MyString.getMemInfo(recByte.length)});
}
} else if (getCommunicationLogging()) {
appLogger.log(Level.FINE,
"Got BINARY [{0}] : {1}", new Object[]{getHostAddress(),
MyString.getMemInfo(recByte.length)});
}
totalReadBytes = totalReadBytes + recByte.length;
if(authorised == false)
authStatus = clientAuthenticationHandler.handleAuthentication(this, recByte);
else
clientBinaryHandler.handleBinary(this, recByte);
} else {
throw new IllegalStateException("Incoming DataMode is not supported: "+dataModeIN);
}
updateLastCommunicationTime();
while(authStatus==AuthStatus.FAILURE)
authStatus = processAuthorisation();
if(authStatus==AuthStatus.SUCCESS)
authorised = true;
} catch(SocketTimeoutException e) {
handleTimeout(e);
}
}//end of while
}
protected void returnClientHandler() {
logger.finest(getName());
super.returnClientHandler();
}
public void setDataMode(DataMode dataMode, DataType dataType)
throws IOException {
if(getDataMode(dataType)==dataMode) return;
appLogger.log(Level.FINE, "Setting Type:{0}, Mode:{1}", new Object[]{dataType, dataMode});
super.checkDataModeSet(dataMode, dataType);
setDataModeBlocking(dataMode, dataType);
}
private void setDataModeBlocking(DataMode dataMode, DataType dataType)
throws IOException {
logger.finest("ENTER");
if(dataMode == DataMode.STRING) {
if(dataType == DataType.OUT) {
if(dataModeOUT == DataMode.BYTE || dataModeOUT == DataMode.BINARY) {
dataModeOUT = dataMode;
} else if(dataModeOUT == DataMode.OBJECT) {
dataModeOUT = dataMode;
o_out.flush(); o_out = null;
b_out = new BufferedOutputStream(out);
} else {
Assertion.affirm(false, "Unknown DataType.OUT DataMode - "+dataModeOUT);
}
Assertion.affirm(b_out!=null, "BufferedOutputStream is still null!");
} else if(dataType == DataType.IN) {
dataModeIN = dataMode;
if(o_in!=null) {
if(o_in.available()!=0)
logger.warning("Data looks to be present in ObjectInputStream");
o_in = null;
}
if(b_in!=null) {
if(b_in.available()!=0)
logger.warning("Data looks to be present in BufferedInputStream");
b_in = null;
}
bufferedReader = new BufferedReader(new InputStreamReader(in, charset));
Assertion.affirm(bufferedReader!=null, "BufferedReader is still null!");
}
} else if(dataMode == DataMode.OBJECT) {
if(dataType == DataType.OUT) {
dataModeOUT = dataMode;
if(b_out!=null) {
b_out.flush();
b_out = null;
}
o_out = new ObjectOutputStream(out);
Assertion.affirm(o_out!=null, "ObjectOutputStream is still null!");
} else if(dataType == DataType.IN) {
dataModeIN = dataMode;
if(b_in!=null) {
if(b_in.available()!=0)
logger.warning("Data looks to be present in BufferedInputStream");
b_in = null;
}
bufferedReader = null;
o_in = new ObjectInputStream(in); //will block
Assertion.affirm(o_in!=null, "ObjectInputStream is still null!");
}
} else if(dataMode == DataMode.BYTE || dataMode == DataMode.BINARY) {
if(dataType == DataType.OUT) {
if(dataModeOUT == DataMode.STRING || dataModeOUT == DataMode.BYTE ||
dataModeOUT == DataMode.BINARY) {
dataModeOUT = dataMode;
} else if(dataModeOUT == DataMode.OBJECT) {
dataModeOUT = dataMode;
if(o_out!=null) {
o_out.flush();
o_out = null;
}
b_out = new BufferedOutputStream(out);
} else {
Assertion.affirm(false, "Unknown DataType.OUT - DataMode: "+dataModeOUT);
}
Assertion.affirm(b_out!=null, "BufferedOutputStream is still null!");
} else if(dataType == DataType.IN) {
dataModeIN = dataMode;
if(o_in!=null) {
if(o_in.available()!=0)
logger.warning("Data looks to be present in ObjectInputStream");
o_in = null;
}
bufferedReader = null;
b_in = new BufferedInputStream(in);
Assertion.affirm(b_in!=null, "BufferedInputStream is still null!");
} else {
throw new IllegalArgumentException("Unknown DataType : "+dataType);
}
} else {
throw new IllegalArgumentException("Unknown DataMode : "+dataMode);
}
}
protected byte[] readInputStream() throws IOException {
return readInputStream(b_in);
}
public void updateInputOutputStreams() throws IOException {
setInputStream(getSocket().getInputStream());
setOutputStream(getSocket().getOutputStream());
}
public boolean getBlockingMode() {
return true;
}
public void setSocketChannel(SocketChannel socketChannel) {
if(true) throw new IllegalStateException("Can't set in blocking mode!");
}
public SocketChannel getSocketChannel() {
if(true) throw new IllegalStateException("Can't get in blocking mode!");
return null;
}
public void setSelectionKey(SelectionKey selectionKey) {
if(true) throw new IllegalStateException("Can't set in blocking mode!");
}
public SelectionKey getSelectionKey() {
if(true) throw new IllegalStateException("Can't get in blocking mode!");
return null;
}
public void registerForRead() throws IOException, ClosedChannelException {
if(true) throw new IllegalStateException("Can't register in blocking mode!");
}
public void registerForWrite() throws IOException, ClosedChannelException {
if(true) throw new IllegalStateException("Can't register in blocking mode!");
}
protected void setClientWriteHandler(ClientWriteHandler handler) {
if(true) throw new IllegalStateException("Can't register in blocking mode!");
}
}