/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License.
*/ package org.apache.tomcat.websocket;
privatefinal Log log = LogFactory.getLog(WsFrameClient.class); // must not be static privatestaticfinal StringManager sm = StringManager.getManager(WsFrameClient.class);
privatefinal AsyncChannelWrapper channel; privatefinal CompletionHandler<Integer, Void> handler; // Not final as it may need to be re-sized privatevolatile ByteBuffer response;
privatevoid processSocketRead() throws IOException { while (true) { switch (getReadState()) { case WAITING: if (!changeReadState(ReadState.WAITING, ReadState.PROCESSING)) { continue;
} while (response.hasRemaining()) { if (isSuspended()) { if (!changeReadState(ReadState.SUSPENDING_PROCESS, ReadState.SUSPENDED)) { continue;
} // There is still data available in the response buffer // Return here so that the response buffer will not be // cleared and there will be no data read from the // socket. Thus when the read operation is resumed first // the data left in the response buffer will be consumed // and then a new socket read will be performed return;
}
inputBuffer.mark();
inputBuffer.position(inputBuffer.limit()).limit(inputBuffer.capacity());
int toCopy = Math.min(response.remaining(), inputBuffer.remaining());
// Copy remaining bytes read in HTTP phase to input buffer used by // frame processing
int orgLimit = response.limit();
response.limit(response.position() + toCopy);
inputBuffer.put(response);
response.limit(orgLimit);
// Process the data we have
processInputBuffer();
}
response.clear();
// Get some more data if (isOpen()) {
channel.read(response, null, handler);
} else {
changeReadState(ReadState.CLOSING);
} return; case SUSPENDING_WAIT: if (!changeReadState(ReadState.SUSPENDING_WAIT, ReadState.SUSPENDED)) { continue;
} return; default: thrownew IllegalStateException(sm.getString("wsFrameServer.illegalReadState", getReadState()));
}
}
}
/* * Fatal error. Usually an I/O error. Try and send notifications. Make sure socket is closed.
*/ privatevoid close(Throwable t) {
changeReadState(ReadState.CLOSING);
CloseReason cr; if (t instanceof WsIOException) {
cr = ((WsIOException) t).getCloseReason();
} else {
cr = new CloseReason(CloseCodes.CLOSED_ABNORMALLY, t.getMessage());
}
wsSession.doClose(cr, cr, true);
}
@Override protectedboolean isMasked() { // Data is from the server so it is not masked returnfalse;
}
@Override publicvoid completed(Integer result, Void attachment) { if (result.intValue() == -1) { // BZ 57762. A dropped connection will get reported as EOF // rather than as an error so handle it here. if (isOpen()) { // No close frame was received
close(new EOFException());
} // No data to process return;
}
response.flip();
doResumeProcessing(true);
}
@Override publicvoid failed(Throwable exc, Void attachment) { if (log.isDebugEnabled()) {
log.debug(sm.getString("wsFrame.readFailed"), exc);
} if (exc instanceof ReadBufferOverflowException) { // response will be empty if this exception is thrown
response = ByteBuffer.allocate(((ReadBufferOverflowException) exc).getMinBufferSize());
response.flip();
doResumeProcessing(false);
} else {
close(exc);
}
}
privatevoid doResumeProcessing(boolean checkOpenOnError) { while (true) { switch (getReadState()) { case PROCESSING: if (!changeReadState(ReadState.PROCESSING, ReadState.WAITING)) { continue;
}
resumeProcessing(checkOpenOnError); return; case SUSPENDING_PROCESS: if (!changeReadState(ReadState.SUSPENDING_PROCESS, ReadState.SUSPENDED)) { continue;
} return; default: thrownew IllegalStateException(sm.getString("wsFrame.illegalReadState", getReadState()));
}
}
}
}
privatevoid resumeProcessing(boolean checkOpenOnError) { try {
processSocketRead();
} catch (IOException e) { if (checkOpenOnError) { // Only send a close message on an IOException if the client // has not yet received a close control message from the server // as the IOException may be in response to the client // continuing to send a message after the server sent a close // control message. if (isOpen()) { if (log.isDebugEnabled()) {
log.debug(sm.getString("wsFrameClient.ioe"), e);
}
close(e);
}
} else {
close(e);
}
}
}
}
¤ Dauer der Verarbeitung: 0.16 Sekunden
(vorverarbeitet)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung ist noch experimentell.