init
This commit is contained in:
151
java/org/apache/tomcat/websocket/AsyncChannelGroupUtil.java
Normal file
151
java/org/apache/tomcat/websocket/AsyncChannelGroupUtil.java
Normal file
@@ -0,0 +1,151 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.channels.AsynchronousChannelGroup;
|
||||
import java.security.AccessController;
|
||||
import java.security.PrivilegedAction;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.SynchronousQueue;
|
||||
import java.util.concurrent.ThreadFactory;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
import org.apache.tomcat.util.res.StringManager;
|
||||
import org.apache.tomcat.util.threads.ThreadPoolExecutor;
|
||||
|
||||
/**
|
||||
* This is a utility class that enables multiple {@link WsWebSocketContainer}
|
||||
* instances to share a single {@link AsynchronousChannelGroup} while ensuring
|
||||
* that the group is destroyed when no longer required.
|
||||
*/
|
||||
public class AsyncChannelGroupUtil {
|
||||
|
||||
private static final StringManager sm =
|
||||
StringManager.getManager(AsyncChannelGroupUtil.class);
|
||||
|
||||
private static AsynchronousChannelGroup group = null;
|
||||
private static int usageCount = 0;
|
||||
private static final Object lock = new Object();
|
||||
|
||||
|
||||
private AsyncChannelGroupUtil() {
|
||||
// Hide the default constructor
|
||||
}
|
||||
|
||||
|
||||
public static AsynchronousChannelGroup register() {
|
||||
synchronized (lock) {
|
||||
if (usageCount == 0) {
|
||||
group = createAsynchronousChannelGroup();
|
||||
}
|
||||
usageCount++;
|
||||
return group;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static void unregister() {
|
||||
synchronized (lock) {
|
||||
usageCount--;
|
||||
if (usageCount == 0) {
|
||||
group.shutdown();
|
||||
group = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static AsynchronousChannelGroup createAsynchronousChannelGroup() {
|
||||
// Need to do this with the right thread context class loader else the
|
||||
// first web app to call this will trigger a leak
|
||||
ClassLoader original = Thread.currentThread().getContextClassLoader();
|
||||
|
||||
try {
|
||||
Thread.currentThread().setContextClassLoader(
|
||||
AsyncIOThreadFactory.class.getClassLoader());
|
||||
|
||||
// These are the same settings as the default
|
||||
// AsynchronousChannelGroup
|
||||
int initialSize = Runtime.getRuntime().availableProcessors();
|
||||
ExecutorService executorService = new ThreadPoolExecutor(
|
||||
0,
|
||||
Integer.MAX_VALUE,
|
||||
Long.MAX_VALUE, TimeUnit.MILLISECONDS,
|
||||
new SynchronousQueue<Runnable>(),
|
||||
new AsyncIOThreadFactory());
|
||||
|
||||
try {
|
||||
return AsynchronousChannelGroup.withCachedThreadPool(
|
||||
executorService, initialSize);
|
||||
} catch (IOException e) {
|
||||
// No good reason for this to happen.
|
||||
throw new IllegalStateException(sm.getString("asyncChannelGroup.createFail"));
|
||||
}
|
||||
} finally {
|
||||
Thread.currentThread().setContextClassLoader(original);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static class AsyncIOThreadFactory implements ThreadFactory {
|
||||
|
||||
static {
|
||||
// Load NewThreadPrivilegedAction since newThread() will not be able
|
||||
// to if called from an InnocuousThread.
|
||||
// See https://bz.apache.org/bugzilla/show_bug.cgi?id=57490
|
||||
NewThreadPrivilegedAction.load();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Thread newThread(final Runnable r) {
|
||||
// Create the new Thread within a doPrivileged block to ensure that
|
||||
// the thread inherits the current ProtectionDomain which is
|
||||
// essential to be able to use this with a Java Applet. See
|
||||
// https://bz.apache.org/bugzilla/show_bug.cgi?id=57091
|
||||
return AccessController.doPrivileged(new NewThreadPrivilegedAction(r));
|
||||
}
|
||||
|
||||
// Non-anonymous class so that AsyncIOThreadFactory can load it
|
||||
// explicitly
|
||||
private static class NewThreadPrivilegedAction implements PrivilegedAction<Thread> {
|
||||
|
||||
private static AtomicInteger count = new AtomicInteger(0);
|
||||
|
||||
private final Runnable r;
|
||||
|
||||
public NewThreadPrivilegedAction(Runnable r) {
|
||||
this.r = r;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Thread run() {
|
||||
Thread t = new Thread(r);
|
||||
t.setName("WebSocketClient-AsyncIO-" + count.incrementAndGet());
|
||||
t.setContextClassLoader(this.getClass().getClassLoader());
|
||||
t.setDaemon(true);
|
||||
return t;
|
||||
}
|
||||
|
||||
private static void load() {
|
||||
// NO-OP. Just provides a hook to enable the class to be loaded
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
47
java/org/apache/tomcat/websocket/AsyncChannelWrapper.java
Normal file
47
java/org/apache/tomcat/websocket/AsyncChannelWrapper.java
Normal file
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.channels.CompletionHandler;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import javax.net.ssl.SSLException;
|
||||
|
||||
/**
|
||||
* This is a wrapper for a {@link java.nio.channels.AsynchronousSocketChannel}
|
||||
* that limits the methods available thereby simplifying the process of
|
||||
* implementing SSL/TLS support since there are fewer methods to intercept.
|
||||
*/
|
||||
public interface AsyncChannelWrapper {
|
||||
|
||||
Future<Integer> read(ByteBuffer dst);
|
||||
|
||||
<B,A extends B> void read(ByteBuffer dst, A attachment,
|
||||
CompletionHandler<Integer,B> handler);
|
||||
|
||||
Future<Integer> write(ByteBuffer src);
|
||||
|
||||
<B,A extends B> void write(ByteBuffer[] srcs, int offset, int length,
|
||||
long timeout, TimeUnit unit, A attachment,
|
||||
CompletionHandler<Long,B> handler);
|
||||
|
||||
void close();
|
||||
|
||||
Future<Void> handshake() throws SSLException;
|
||||
}
|
||||
@@ -0,0 +1,112 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.channels.AsynchronousSocketChannel;
|
||||
import java.nio.channels.CompletionHandler;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
|
||||
/**
|
||||
* Generally, just passes calls straight to the wrapped
|
||||
* {@link AsynchronousSocketChannel}. In some cases exceptions may be swallowed
|
||||
* to save them being swallowed by the calling code.
|
||||
*/
|
||||
public class AsyncChannelWrapperNonSecure implements AsyncChannelWrapper {
|
||||
|
||||
private static final Future<Void> NOOP_FUTURE = new NoOpFuture();
|
||||
|
||||
private final AsynchronousSocketChannel socketChannel;
|
||||
|
||||
public AsyncChannelWrapperNonSecure(
|
||||
AsynchronousSocketChannel socketChannel) {
|
||||
this.socketChannel = socketChannel;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Future<Integer> read(ByteBuffer dst) {
|
||||
return socketChannel.read(dst);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <B,A extends B> void read(ByteBuffer dst, A attachment,
|
||||
CompletionHandler<Integer,B> handler) {
|
||||
socketChannel.read(dst, attachment, handler);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Future<Integer> write(ByteBuffer src) {
|
||||
return socketChannel.write(src);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <B,A extends B> void write(ByteBuffer[] srcs, int offset, int length,
|
||||
long timeout, TimeUnit unit, A attachment,
|
||||
CompletionHandler<Long,B> handler) {
|
||||
socketChannel.write(
|
||||
srcs, offset, length, timeout, unit, attachment, handler);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
try {
|
||||
socketChannel.close();
|
||||
} catch (IOException e) {
|
||||
// Ignore
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Future<Void> handshake() {
|
||||
return NOOP_FUTURE;
|
||||
}
|
||||
|
||||
|
||||
private static final class NoOpFuture implements Future<Void> {
|
||||
|
||||
@Override
|
||||
public boolean cancel(boolean mayInterruptIfRunning) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCancelled() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDone() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void get() throws InterruptedException, ExecutionException {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void get(long timeout, TimeUnit unit)
|
||||
throws InterruptedException, ExecutionException,
|
||||
TimeoutException {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
578
java/org/apache/tomcat/websocket/AsyncChannelWrapperSecure.java
Normal file
578
java/org/apache/tomcat/websocket/AsyncChannelWrapperSecure.java
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
/**
|
||||
* Exception thrown on authentication error connecting to a remote
|
||||
* websocket endpoint.
|
||||
*/
|
||||
public class AuthenticationException extends Exception {
|
||||
|
||||
private static final long serialVersionUID = 5709887412240096441L;
|
||||
|
||||
/**
|
||||
* Create authentication exception.
|
||||
* @param message the error message
|
||||
*/
|
||||
public AuthenticationException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
}
|
||||
71
java/org/apache/tomcat/websocket/Authenticator.java
Normal file
71
java/org/apache/tomcat/websocket/Authenticator.java
Normal file
@@ -0,0 +1,71 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* Base class for the authentication methods used by the websocket client.
|
||||
*/
|
||||
public abstract class Authenticator {
|
||||
private static final Pattern pattern = Pattern
|
||||
.compile("(\\w+)\\s*=\\s*(\"([^\"]+)\"|([^,=\"]+))\\s*,?");
|
||||
|
||||
/**
|
||||
* Generate the authentication header that will be sent to the server.
|
||||
* @param requestUri The request URI
|
||||
* @param WWWAuthenticate The server auth challenge
|
||||
* @param UserProperties The user information
|
||||
* @return The auth header
|
||||
* @throws AuthenticationException When an error occurs
|
||||
*/
|
||||
public abstract String getAuthorization(String requestUri, String WWWAuthenticate,
|
||||
Map<String, Object> UserProperties) throws AuthenticationException;
|
||||
|
||||
/**
|
||||
* Get the authentication method.
|
||||
* @return the auth scheme
|
||||
*/
|
||||
public abstract String getSchemeName();
|
||||
|
||||
/**
|
||||
* Utility method to parse the authentication header.
|
||||
* @param WWWAuthenticate The server auth challenge
|
||||
* @return the parsed header
|
||||
*/
|
||||
public Map<String, String> parseWWWAuthenticateHeader(String WWWAuthenticate) {
|
||||
|
||||
Matcher m = pattern.matcher(WWWAuthenticate);
|
||||
Map<String, String> challenge = new HashMap<>();
|
||||
|
||||
while (m.find()) {
|
||||
String key = m.group(1);
|
||||
String qtedValue = m.group(3);
|
||||
String value = m.group(4);
|
||||
|
||||
challenge.put(key, qtedValue != null ? qtedValue : value);
|
||||
|
||||
}
|
||||
|
||||
return challenge;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
68
java/org/apache/tomcat/websocket/AuthenticatorFactory.java
Normal file
68
java/org/apache/tomcat/websocket/AuthenticatorFactory.java
Normal file
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.ServiceLoader;
|
||||
|
||||
/**
|
||||
* Utility method to return the appropriate authenticator according to
|
||||
* the scheme that the server uses.
|
||||
*/
|
||||
public class AuthenticatorFactory {
|
||||
|
||||
/**
|
||||
* Return a new authenticator instance.
|
||||
* @param authScheme The scheme used
|
||||
* @return the authenticator
|
||||
*/
|
||||
public static Authenticator getAuthenticator(String authScheme) {
|
||||
|
||||
Authenticator auth = null;
|
||||
switch (authScheme.toLowerCase()) {
|
||||
|
||||
case BasicAuthenticator.schemeName:
|
||||
auth = new BasicAuthenticator();
|
||||
break;
|
||||
|
||||
case DigestAuthenticator.schemeName:
|
||||
auth = new DigestAuthenticator();
|
||||
break;
|
||||
|
||||
default:
|
||||
auth = loadAuthenticators(authScheme);
|
||||
break;
|
||||
}
|
||||
|
||||
return auth;
|
||||
|
||||
}
|
||||
|
||||
private static Authenticator loadAuthenticators(String authScheme) {
|
||||
ServiceLoader<Authenticator> serviceLoader = ServiceLoader.load(Authenticator.class);
|
||||
Iterator<Authenticator> auths = serviceLoader.iterator();
|
||||
|
||||
while (auths.hasNext()) {
|
||||
Authenticator auth = auths.next();
|
||||
if (auth.getSchemeName().equalsIgnoreCase(authScheme))
|
||||
return auth;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
26
java/org/apache/tomcat/websocket/BackgroundProcess.java
Normal file
26
java/org/apache/tomcat/websocket/BackgroundProcess.java
Normal file
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
public interface BackgroundProcess {
|
||||
|
||||
void backgroundProcess();
|
||||
|
||||
void setProcessPeriod(int period);
|
||||
|
||||
int getProcessPeriod();
|
||||
}
|
||||
149
java/org/apache/tomcat/websocket/BackgroundProcessManager.java
Normal file
149
java/org/apache/tomcat/websocket/BackgroundProcessManager.java
Normal file
@@ -0,0 +1,149 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import org.apache.juli.logging.Log;
|
||||
import org.apache.juli.logging.LogFactory;
|
||||
import org.apache.tomcat.util.ExceptionUtils;
|
||||
import org.apache.tomcat.util.res.StringManager;
|
||||
|
||||
/**
|
||||
* Provides a background processing mechanism that triggers roughly once a
|
||||
* second. The class maintains a thread that only runs when there is at least
|
||||
* one instance of {@link BackgroundProcess} registered.
|
||||
*/
|
||||
public class BackgroundProcessManager {
|
||||
|
||||
private final Log log =
|
||||
LogFactory.getLog(BackgroundProcessManager.class);
|
||||
private static final StringManager sm =
|
||||
StringManager.getManager(BackgroundProcessManager.class);
|
||||
private static final BackgroundProcessManager instance;
|
||||
|
||||
|
||||
static {
|
||||
instance = new BackgroundProcessManager();
|
||||
}
|
||||
|
||||
|
||||
public static BackgroundProcessManager getInstance() {
|
||||
return instance;
|
||||
}
|
||||
|
||||
private final Set<BackgroundProcess> processes = new HashSet<>();
|
||||
private final Object processesLock = new Object();
|
||||
private WsBackgroundThread wsBackgroundThread = null;
|
||||
|
||||
private BackgroundProcessManager() {
|
||||
// Hide default constructor
|
||||
}
|
||||
|
||||
|
||||
public void register(BackgroundProcess process) {
|
||||
synchronized (processesLock) {
|
||||
if (processes.size() == 0) {
|
||||
wsBackgroundThread = new WsBackgroundThread(this);
|
||||
wsBackgroundThread.setContextClassLoader(
|
||||
this.getClass().getClassLoader());
|
||||
wsBackgroundThread.setDaemon(true);
|
||||
wsBackgroundThread.start();
|
||||
}
|
||||
processes.add(process);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void unregister(BackgroundProcess process) {
|
||||
synchronized (processesLock) {
|
||||
processes.remove(process);
|
||||
if (wsBackgroundThread != null && processes.size() == 0) {
|
||||
wsBackgroundThread.halt();
|
||||
wsBackgroundThread = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void process() {
|
||||
Set<BackgroundProcess> currentProcesses = new HashSet<>();
|
||||
synchronized (processesLock) {
|
||||
currentProcesses.addAll(processes);
|
||||
}
|
||||
for (BackgroundProcess process : currentProcesses) {
|
||||
try {
|
||||
process.backgroundProcess();
|
||||
} catch (Throwable t) {
|
||||
ExceptionUtils.handleThrowable(t);
|
||||
log.error(sm.getString(
|
||||
"backgroundProcessManager.processFailed"), t);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* For unit testing.
|
||||
*/
|
||||
int getProcessCount() {
|
||||
synchronized (processesLock) {
|
||||
return processes.size();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void shutdown() {
|
||||
synchronized (processesLock) {
|
||||
processes.clear();
|
||||
if (wsBackgroundThread != null) {
|
||||
wsBackgroundThread.halt();
|
||||
wsBackgroundThread = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static class WsBackgroundThread extends Thread {
|
||||
|
||||
private final BackgroundProcessManager manager;
|
||||
private volatile boolean running = true;
|
||||
|
||||
public WsBackgroundThread(BackgroundProcessManager manager) {
|
||||
setName("WebSocket background processing");
|
||||
this.manager = manager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
while (running) {
|
||||
try {
|
||||
Thread.sleep(1000);
|
||||
} catch (InterruptedException e) {
|
||||
// Ignore
|
||||
}
|
||||
manager.process();
|
||||
}
|
||||
}
|
||||
|
||||
public void halt() {
|
||||
setName("WebSocket background processing - stopping");
|
||||
running = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
67
java/org/apache/tomcat/websocket/BasicAuthenticator.java
Normal file
67
java/org/apache/tomcat/websocket/BasicAuthenticator.java
Normal file
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import java.nio.charset.Charset;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.tomcat.util.codec.binary.Base64;
|
||||
|
||||
/**
|
||||
* Authenticator supporting the BASIC auth method.
|
||||
*/
|
||||
public class BasicAuthenticator extends Authenticator {
|
||||
|
||||
public static final String schemeName = "basic";
|
||||
public static final String charsetparam = "charset";
|
||||
|
||||
@Override
|
||||
public String getAuthorization(String requestUri, String WWWAuthenticate,
|
||||
Map<String, Object> userProperties) throws AuthenticationException {
|
||||
|
||||
String userName = (String) userProperties.get(Constants.WS_AUTHENTICATION_USER_NAME);
|
||||
String password = (String) userProperties.get(Constants.WS_AUTHENTICATION_PASSWORD);
|
||||
|
||||
if (userName == null || password == null) {
|
||||
throw new AuthenticationException(
|
||||
"Failed to perform Basic authentication due to missing user/password");
|
||||
}
|
||||
|
||||
Map<String, String> wwwAuthenticate = parseWWWAuthenticateHeader(WWWAuthenticate);
|
||||
|
||||
String userPass = userName + ":" + password;
|
||||
Charset charset;
|
||||
|
||||
if (wwwAuthenticate.get(charsetparam) != null
|
||||
&& wwwAuthenticate.get(charsetparam).equalsIgnoreCase("UTF-8")) {
|
||||
charset = StandardCharsets.UTF_8;
|
||||
} else {
|
||||
charset = StandardCharsets.ISO_8859_1;
|
||||
}
|
||||
|
||||
String base64 = Base64.encodeBase64String(userPass.getBytes(charset));
|
||||
|
||||
return " Basic " + base64;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSchemeName() {
|
||||
return schemeName;
|
||||
}
|
||||
|
||||
}
|
||||
154
java/org/apache/tomcat/websocket/Constants.java
Normal file
154
java/org/apache/tomcat/websocket/Constants.java
Normal file
@@ -0,0 +1,154 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import javax.websocket.Extension;
|
||||
|
||||
/**
|
||||
* Internal implementation constants.
|
||||
*/
|
||||
public class Constants {
|
||||
|
||||
// OP Codes
|
||||
public static final byte OPCODE_CONTINUATION = 0x00;
|
||||
public static final byte OPCODE_TEXT = 0x01;
|
||||
public static final byte OPCODE_BINARY = 0x02;
|
||||
public static final byte OPCODE_CLOSE = 0x08;
|
||||
public static final byte OPCODE_PING = 0x09;
|
||||
public static final byte OPCODE_PONG = 0x0A;
|
||||
|
||||
// Internal OP Codes
|
||||
// RFC 6455 limits OP Codes to 4 bits so these should never clash
|
||||
// Always set bit 4 so these will be treated as control codes
|
||||
static final byte INTERNAL_OPCODE_FLUSH = 0x18;
|
||||
|
||||
// Buffers
|
||||
static final int DEFAULT_BUFFER_SIZE = Integer.getInteger(
|
||||
"org.apache.tomcat.websocket.DEFAULT_BUFFER_SIZE", 8 * 1024)
|
||||
.intValue();
|
||||
|
||||
// Client connection
|
||||
/**
|
||||
* Property name to set to configure the value that is passed to
|
||||
* {@link javax.net.ssl.SSLEngine#setEnabledProtocols(String[])}. The value
|
||||
* should be a comma separated string.
|
||||
*/
|
||||
public static final String SSL_PROTOCOLS_PROPERTY =
|
||||
"org.apache.tomcat.websocket.SSL_PROTOCOLS";
|
||||
public static final String SSL_TRUSTSTORE_PROPERTY =
|
||||
"org.apache.tomcat.websocket.SSL_TRUSTSTORE";
|
||||
public static final String SSL_TRUSTSTORE_PWD_PROPERTY =
|
||||
"org.apache.tomcat.websocket.SSL_TRUSTSTORE_PWD";
|
||||
public static final String SSL_TRUSTSTORE_PWD_DEFAULT = "changeit";
|
||||
/**
|
||||
* Property name to set to configure used SSLContext. The value should be an
|
||||
* instance of SSLContext. If this property is present, the SSL_TRUSTSTORE*
|
||||
* properties are ignored.
|
||||
*/
|
||||
public static final String SSL_CONTEXT_PROPERTY =
|
||||
"org.apache.tomcat.websocket.SSL_CONTEXT";
|
||||
/**
|
||||
* Property name to set to configure the timeout (in milliseconds) when
|
||||
* establishing a WebSocket connection to server. The default is
|
||||
* {@link #IO_TIMEOUT_MS_DEFAULT}.
|
||||
*/
|
||||
public static final String IO_TIMEOUT_MS_PROPERTY =
|
||||
"org.apache.tomcat.websocket.IO_TIMEOUT_MS";
|
||||
public static final long IO_TIMEOUT_MS_DEFAULT = 5000;
|
||||
|
||||
// RFC 2068 recommended a limit of 5
|
||||
// Most browsers have a default limit of 20
|
||||
public static final String MAX_REDIRECTIONS_PROPERTY =
|
||||
"org.apache.tomcat.websocket.MAX_REDIRECTIONS";
|
||||
public static final int MAX_REDIRECTIONS_DEFAULT = 20;
|
||||
|
||||
// HTTP upgrade header names and values
|
||||
public static final String HOST_HEADER_NAME = "Host";
|
||||
public static final String UPGRADE_HEADER_NAME = "Upgrade";
|
||||
public static final String UPGRADE_HEADER_VALUE = "websocket";
|
||||
public static final String ORIGIN_HEADER_NAME = "Origin";
|
||||
public static final String CONNECTION_HEADER_NAME = "Connection";
|
||||
public static final String CONNECTION_HEADER_VALUE = "upgrade";
|
||||
public static final String LOCATION_HEADER_NAME = "Location";
|
||||
public static final String AUTHORIZATION_HEADER_NAME = "Authorization";
|
||||
public static final String WWW_AUTHENTICATE_HEADER_NAME = "WWW-Authenticate";
|
||||
public static final String WS_VERSION_HEADER_NAME = "Sec-WebSocket-Version";
|
||||
public static final String WS_VERSION_HEADER_VALUE = "13";
|
||||
public static final String WS_KEY_HEADER_NAME = "Sec-WebSocket-Key";
|
||||
public static final String WS_PROTOCOL_HEADER_NAME = "Sec-WebSocket-Protocol";
|
||||
public static final String WS_EXTENSIONS_HEADER_NAME = "Sec-WebSocket-Extensions";
|
||||
|
||||
/// HTTP redirection status codes
|
||||
public static final int MULTIPLE_CHOICES = 300;
|
||||
public static final int MOVED_PERMANENTLY = 301;
|
||||
public static final int FOUND = 302;
|
||||
public static final int SEE_OTHER = 303;
|
||||
public static final int USE_PROXY = 305;
|
||||
public static final int TEMPORARY_REDIRECT = 307;
|
||||
|
||||
// Configuration for Origin header in client
|
||||
static final String DEFAULT_ORIGIN_HEADER_VALUE =
|
||||
System.getProperty("org.apache.tomcat.websocket.DEFAULT_ORIGIN_HEADER_VALUE");
|
||||
|
||||
// Configuration for blocking sends
|
||||
public static final String BLOCKING_SEND_TIMEOUT_PROPERTY =
|
||||
"org.apache.tomcat.websocket.BLOCKING_SEND_TIMEOUT";
|
||||
// Milliseconds so this is 20 seconds
|
||||
public static final long DEFAULT_BLOCKING_SEND_TIMEOUT = 20 * 1000;
|
||||
|
||||
// Configuration for background processing checks intervals
|
||||
static final int DEFAULT_PROCESS_PERIOD = Integer.getInteger(
|
||||
"org.apache.tomcat.websocket.DEFAULT_PROCESS_PERIOD", 10)
|
||||
.intValue();
|
||||
|
||||
public static final String WS_AUTHENTICATION_USER_NAME = "org.apache.tomcat.websocket.WS_AUTHENTICATION_USER_NAME";
|
||||
public static final String WS_AUTHENTICATION_PASSWORD = "org.apache.tomcat.websocket.WS_AUTHENTICATION_PASSWORD";
|
||||
|
||||
/* Configuration for extensions
|
||||
* Note: These options are primarily present to enable this implementation
|
||||
* to pass compliance tests. They are expected to be removed once
|
||||
* the WebSocket API includes a mechanism for adding custom extensions
|
||||
* and disabling built-in extensions.
|
||||
*/
|
||||
static final boolean DISABLE_BUILTIN_EXTENSIONS =
|
||||
Boolean.getBoolean("org.apache.tomcat.websocket.DISABLE_BUILTIN_EXTENSIONS");
|
||||
static final boolean ALLOW_UNSUPPORTED_EXTENSIONS =
|
||||
Boolean.getBoolean("org.apache.tomcat.websocket.ALLOW_UNSUPPORTED_EXTENSIONS");
|
||||
|
||||
public static final boolean STRICT_SPEC_COMPLIANCE =
|
||||
Boolean.getBoolean("org.apache.tomcat.websocket.STRICT_SPEC_COMPLIANCE");
|
||||
|
||||
public static final List<Extension> INSTALLED_EXTENSIONS;
|
||||
|
||||
static {
|
||||
if (DISABLE_BUILTIN_EXTENSIONS) {
|
||||
INSTALLED_EXTENSIONS = Collections.unmodifiableList(new ArrayList<Extension>());
|
||||
} else {
|
||||
List<Extension> installed = new ArrayList<>(1);
|
||||
installed.add(new WsExtension("permessage-deflate"));
|
||||
INSTALLED_EXTENSIONS = Collections.unmodifiableList(installed);
|
||||
}
|
||||
}
|
||||
|
||||
private Constants() {
|
||||
// Hide default constructor
|
||||
}
|
||||
}
|
||||
39
java/org/apache/tomcat/websocket/DecoderEntry.java
Normal file
39
java/org/apache/tomcat/websocket/DecoderEntry.java
Normal file
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import javax.websocket.Decoder;
|
||||
|
||||
public class DecoderEntry {
|
||||
|
||||
private final Class<?> clazz;
|
||||
private final Class<? extends Decoder> decoderClazz;
|
||||
|
||||
public DecoderEntry(Class<?> clazz,
|
||||
Class<? extends Decoder> decoderClazz) {
|
||||
this.clazz = clazz;
|
||||
this.decoderClazz = decoderClazz;
|
||||
}
|
||||
|
||||
public Class<?> getClazz() {
|
||||
return clazz;
|
||||
}
|
||||
|
||||
public Class<? extends Decoder> getDecoderClazz() {
|
||||
return decoderClazz;
|
||||
}
|
||||
}
|
||||
150
java/org/apache/tomcat/websocket/DigestAuthenticator.java
Normal file
150
java/org/apache/tomcat/websocket/DigestAuthenticator.java
Normal file
@@ -0,0 +1,150 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.SecureRandom;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.tomcat.util.security.MD5Encoder;
|
||||
|
||||
/**
|
||||
* Authenticator supporting the DIGEST auth method.
|
||||
*/
|
||||
public class DigestAuthenticator extends Authenticator {
|
||||
|
||||
public static final String schemeName = "digest";
|
||||
private SecureRandom cnonceGenerator;
|
||||
private int nonceCount = 0;
|
||||
private long cNonce;
|
||||
|
||||
@Override
|
||||
public String getAuthorization(String requestUri, String WWWAuthenticate,
|
||||
Map<String, Object> userProperties) throws AuthenticationException {
|
||||
|
||||
String userName = (String) userProperties.get(Constants.WS_AUTHENTICATION_USER_NAME);
|
||||
String password = (String) userProperties.get(Constants.WS_AUTHENTICATION_PASSWORD);
|
||||
|
||||
if (userName == null || password == null) {
|
||||
throw new AuthenticationException(
|
||||
"Failed to perform Digest authentication due to missing user/password");
|
||||
}
|
||||
|
||||
Map<String, String> wwwAuthenticate = parseWWWAuthenticateHeader(WWWAuthenticate);
|
||||
|
||||
String realm = wwwAuthenticate.get("realm");
|
||||
String nonce = wwwAuthenticate.get("nonce");
|
||||
String messageQop = wwwAuthenticate.get("qop");
|
||||
String algorithm = wwwAuthenticate.get("algorithm") == null ? "MD5"
|
||||
: wwwAuthenticate.get("algorithm");
|
||||
String opaque = wwwAuthenticate.get("opaque");
|
||||
|
||||
StringBuilder challenge = new StringBuilder();
|
||||
|
||||
if (!messageQop.isEmpty()) {
|
||||
if (cnonceGenerator == null) {
|
||||
cnonceGenerator = new SecureRandom();
|
||||
}
|
||||
|
||||
cNonce = cnonceGenerator.nextLong();
|
||||
nonceCount++;
|
||||
}
|
||||
|
||||
challenge.append("Digest ");
|
||||
challenge.append("username =\"" + userName + "\",");
|
||||
challenge.append("realm=\"" + realm + "\",");
|
||||
challenge.append("nonce=\"" + nonce + "\",");
|
||||
challenge.append("uri=\"" + requestUri + "\",");
|
||||
|
||||
try {
|
||||
challenge.append("response=\"" + calculateRequestDigest(requestUri, userName, password,
|
||||
realm, nonce, messageQop, algorithm) + "\",");
|
||||
}
|
||||
|
||||
catch (NoSuchAlgorithmException e) {
|
||||
throw new AuthenticationException(
|
||||
"Unable to generate request digest " + e.getMessage());
|
||||
}
|
||||
|
||||
challenge.append("algorithm=" + algorithm + ",");
|
||||
challenge.append("opaque=\"" + opaque + "\",");
|
||||
|
||||
if (!messageQop.isEmpty()) {
|
||||
challenge.append("qop=\"" + messageQop + "\"");
|
||||
challenge.append(",cnonce=\"" + cNonce + "\",");
|
||||
challenge.append("nc=" + String.format("%08X", Integer.valueOf(nonceCount)));
|
||||
}
|
||||
|
||||
return challenge.toString();
|
||||
|
||||
}
|
||||
|
||||
private String calculateRequestDigest(String requestUri, String userName, String password,
|
||||
String realm, String nonce, String qop, String algorithm)
|
||||
throws NoSuchAlgorithmException {
|
||||
|
||||
StringBuilder preDigest = new StringBuilder();
|
||||
String A1;
|
||||
|
||||
if (algorithm.equalsIgnoreCase("MD5"))
|
||||
A1 = userName + ":" + realm + ":" + password;
|
||||
|
||||
else
|
||||
A1 = encodeMD5(userName + ":" + realm + ":" + password) + ":" + nonce + ":" + cNonce;
|
||||
|
||||
/*
|
||||
* If the "qop" value is "auth-int", then A2 is: A2 = Method ":"
|
||||
* digest-uri-value ":" H(entity-body) since we do not have an entity-body, A2 =
|
||||
* Method ":" digest-uri-value for auth and auth_int
|
||||
*/
|
||||
String A2 = "GET:" + requestUri;
|
||||
|
||||
preDigest.append(encodeMD5(A1));
|
||||
preDigest.append(":");
|
||||
preDigest.append(nonce);
|
||||
|
||||
if (qop.toLowerCase().contains("auth")) {
|
||||
preDigest.append(":");
|
||||
preDigest.append(String.format("%08X", Integer.valueOf(nonceCount)));
|
||||
preDigest.append(":");
|
||||
preDigest.append(String.valueOf(cNonce));
|
||||
preDigest.append(":");
|
||||
preDigest.append(qop);
|
||||
}
|
||||
|
||||
preDigest.append(":");
|
||||
preDigest.append(encodeMD5(A2));
|
||||
|
||||
return encodeMD5(preDigest.toString());
|
||||
|
||||
}
|
||||
|
||||
private String encodeMD5(String value) throws NoSuchAlgorithmException {
|
||||
byte[] bytesOfMessage = value.getBytes(StandardCharsets.ISO_8859_1);
|
||||
MessageDigest md = MessageDigest.getInstance("MD5");
|
||||
byte[] thedigest = md.digest(bytesOfMessage);
|
||||
|
||||
return MD5Encoder.encode(thedigest);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSchemeName() {
|
||||
return schemeName;
|
||||
}
|
||||
}
|
||||
112
java/org/apache/tomcat/websocket/FutureToSendHandler.java
Normal file
112
java/org/apache/tomcat/websocket/FutureToSendHandler.java
Normal file
@@ -0,0 +1,112 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
import javax.websocket.SendHandler;
|
||||
import javax.websocket.SendResult;
|
||||
|
||||
import org.apache.tomcat.util.res.StringManager;
|
||||
|
||||
|
||||
/**
|
||||
* Converts a Future to a SendHandler.
|
||||
*/
|
||||
class FutureToSendHandler implements Future<Void>, SendHandler {
|
||||
|
||||
private static final StringManager sm = StringManager.getManager(FutureToSendHandler.class);
|
||||
|
||||
private final CountDownLatch latch = new CountDownLatch(1);
|
||||
private final WsSession wsSession;
|
||||
private volatile AtomicReference<SendResult> result = new AtomicReference<>(null);
|
||||
|
||||
public FutureToSendHandler(WsSession wsSession) {
|
||||
this.wsSession = wsSession;
|
||||
}
|
||||
|
||||
|
||||
// --------------------------------------------------------- SendHandler
|
||||
|
||||
@Override
|
||||
public void onResult(SendResult result) {
|
||||
this.result.compareAndSet(null, result);
|
||||
latch.countDown();
|
||||
}
|
||||
|
||||
|
||||
// -------------------------------------------------------------- Future
|
||||
|
||||
@Override
|
||||
public boolean cancel(boolean mayInterruptIfRunning) {
|
||||
// Cancelling the task is not supported
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCancelled() {
|
||||
// Cancelling the task is not supported
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDone() {
|
||||
return latch.getCount() == 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void get() throws InterruptedException,
|
||||
ExecutionException {
|
||||
try {
|
||||
wsSession.registerFuture(this);
|
||||
latch.await();
|
||||
} finally {
|
||||
wsSession.unregisterFuture(this);
|
||||
}
|
||||
if (result.get().getException() != null) {
|
||||
throw new ExecutionException(result.get().getException());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void get(long timeout, TimeUnit unit)
|
||||
throws InterruptedException, ExecutionException,
|
||||
TimeoutException {
|
||||
boolean retval = false;
|
||||
try {
|
||||
wsSession.registerFuture(this);
|
||||
retval = latch.await(timeout, unit);
|
||||
} finally {
|
||||
wsSession.unregisterFuture(this);
|
||||
|
||||
}
|
||||
if (retval == false) {
|
||||
throw new TimeoutException(sm.getString("futureToSendHandler.timeout",
|
||||
Long.valueOf(timeout), unit.toString().toLowerCase()));
|
||||
}
|
||||
if (result.get().getException() != null) {
|
||||
throw new ExecutionException(result.get().getException());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
146
java/org/apache/tomcat/websocket/LocalStrings.properties
Normal file
146
java/org/apache/tomcat/websocket/LocalStrings.properties
Normal file
@@ -0,0 +1,146 @@
|
||||
# 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.
|
||||
|
||||
asyncChannelGroup.createFail=Unable to create dedicated AsynchronousChannelGroup for WebSocket clients which is required to prevent memory leaks in complex class loader environments like JavaEE containers
|
||||
|
||||
asyncChannelWrapperSecure.check.notOk=TLS handshake returned an unexpected status [{0}]
|
||||
asyncChannelWrapperSecure.check.unwrap=Bytes were written to the output during a read
|
||||
asyncChannelWrapperSecure.check.wrap=Bytes were consumed from the input during a write
|
||||
asyncChannelWrapperSecure.closeFail=Failed to close channel cleanly
|
||||
asyncChannelWrapperSecure.concurrentRead=Concurrent read operations are not permitted
|
||||
asyncChannelWrapperSecure.concurrentWrite=Concurrent write operations are not permitted
|
||||
asyncChannelWrapperSecure.eof=Unexpected end of stream
|
||||
asyncChannelWrapperSecure.notHandshaking=Unexpected state [NOT_HANDSHAKING] during TLS handshake
|
||||
asyncChannelWrapperSecure.statusUnwrap=Unexpected Status of SSLEngineResult after an unwrap() operation
|
||||
asyncChannelWrapperSecure.statusWrap=Unexpected Status of SSLEngineResult after a wrap() operation
|
||||
asyncChannelWrapperSecure.tooBig=The result [{0}] is too big to be expressed as an Integer
|
||||
asyncChannelWrapperSecure.wrongStateRead=Flag that indicates a read is in progress was found to be false (it should have been true) when trying to complete a read operation
|
||||
asyncChannelWrapperSecure.wrongStateWrite=Flag that indicates a write is in progress was found to be false (it should have been true) when trying to complete a write operation
|
||||
|
||||
backgroundProcessManager.processFailed=A background process failed
|
||||
|
||||
caseInsensitiveKeyMap.nullKey=Null keys are not permitted
|
||||
|
||||
futureToSendHandler.timeout=Operation timed out after waiting [{0}] [{1}] to complete
|
||||
|
||||
perMessageDeflate.alreadyClosed=The transformer has been closed and may no longer be used
|
||||
perMessageDeflate.deflateFailed=Failed to decompress a compressed WebSocket frame
|
||||
perMessageDeflate.duplicateParameter=Duplicate definition of the [{0}] extension parameter
|
||||
perMessageDeflate.invalidState=Invalid state
|
||||
perMessageDeflate.invalidWindowSize=An invalid windows of [{1}] size was specified for [{0}]. Valid values are whole numbers from 8 to 15 inclusive.
|
||||
perMessageDeflate.unknownParameter=An unknown extension parameter [{0}] was defined
|
||||
|
||||
transformerFactory.unsupportedExtension=The extension [{0}] is not supported
|
||||
|
||||
util.invalidMessageHandler=The message handler provided does not have an onMessage(Object) method
|
||||
util.invalidType=Unable to coerce value [{0}] to type [{1}]. That type is not supported.
|
||||
util.notToken=An illegal extension parameter was specified with name [{0}] and value [{1}]
|
||||
util.unknownDecoderType=The Decoder type [{0}] is not recognized
|
||||
|
||||
# Note the wsFrame.* messages are used as close reasons in WebSocket control
|
||||
# frames and therefore must be 123 bytes (not characters) or less in length.
|
||||
# Messages are encoded using UTF-8 where a single character may be encoded in
|
||||
# as many as 4 bytes.
|
||||
wsFrame.alreadyResumed=Message receiving has already been resumed.
|
||||
wsFrame.alreadySuspended=Message receiving has already been suspended.
|
||||
wsFrame.bufferTooSmall=No async message support and buffer too small. Buffer size: [{0}], Message size: [{1}]
|
||||
wsFrame.byteToLongFail=Too many bytes ([{0}]) were provided to be converted into a long
|
||||
wsFrame.closed=New frame received after a close control frame
|
||||
wsFrame.controlFragmented=A fragmented control frame was received but control frames may not be fragmented
|
||||
wsFrame.controlNoFin=A control frame was sent that did not have the fin bit set. Control frames are not permitted to use continuation frames.
|
||||
wsFrame.controlPayloadTooBig=A control frame was sent with a payload of size [{0}] which is larger than the maximum permitted of 125 bytes
|
||||
wsFrame.illegalReadState=Unexpected read state [{0}]
|
||||
wsFrame.invalidOpCode=A WebSocket frame was sent with an unrecognised opCode of [{0}]
|
||||
wsFrame.invalidUtf8=A WebSocket text frame was received that could not be decoded to UTF-8 because it contained invalid byte sequences
|
||||
wsFrame.invalidUtf8Close=A WebSocket close frame was received with a close reason that contained invalid UTF-8 byte sequences
|
||||
wsFrame.ioeTriggeredClose=An unrecoverable IOException occurred so the connection was closed
|
||||
wsFrame.messageTooBig=The message was [{0}] bytes long but the MessageHandler has a limit of [{1}] bytes
|
||||
wsFrame.noContinuation=A new message was started when a continuation frame was expected
|
||||
wsFrame.notMasked=The client frame was not masked but all client frames must be masked
|
||||
wsFrame.oneByteCloseCode=The client sent a close frame with a single byte payload which is not valid
|
||||
wsFrame.partialHeaderComplete=WebSocket frame received. fin [{0}], rsv [{1}], OpCode [{2}], payload length [{3}]
|
||||
wsFrame.sessionClosed=The client data cannot be processed because the session has already been closed
|
||||
wsFrame.suspendRequested=Suspend of the message receiving has already been requested.
|
||||
wsFrame.textMessageTooBig=The decoded text message was too big for the output buffer and the endpoint does not support partial messages
|
||||
wsFrame.wrongRsv=The client frame set the reserved bits to [{0}] for a message with opCode [{1}] which was not supported by this endpoint
|
||||
|
||||
wsFrameClient.ioe=Failure while reading data sent by server
|
||||
|
||||
wsHandshakeRequest.invalidUri=The string [{0}] cannot be used to construct a valid URI
|
||||
wsHandshakeRequest.unknownScheme=The scheme [{0}] in the request is not recognised
|
||||
|
||||
wsRemoteEndpoint.acquireTimeout=The current message was not fully sent within the specified timeout
|
||||
wsRemoteEndpoint.changeType=When sending a fragmented message, all fragments must be of the same type
|
||||
wsRemoteEndpoint.closed=Message will not be sent because the WebSocket session has been closed
|
||||
wsRemoteEndpoint.closedDuringMessage=The remainder of the message will not be sent because the WebSocket session has been closed
|
||||
wsRemoteEndpoint.closedOutputStream=This method may not be called as the OutputStream has been closed
|
||||
wsRemoteEndpoint.closedWriter=This method may not be called as the Writer has been closed
|
||||
wsRemoteEndpoint.flushOnCloseFailed=Batched messages still enabled after session has been closed. Unable to flush remaining batched message.
|
||||
wsRemoteEndpoint.invalidEncoder=The specified encoder of type [{0}] could not be instantiated
|
||||
wsRemoteEndpoint.noEncoder=No encoder specified for object of class [{0}]
|
||||
wsRemoteEndpoint.nullData=Invalid null data argument
|
||||
wsRemoteEndpoint.nullHandler=Invalid null handler argument
|
||||
wsRemoteEndpoint.sendInterrupt=The current thread was interrupted while waiting for a blocking send to complete
|
||||
wsRemoteEndpoint.tooMuchData=Ping or pong may not send more than 125 bytes
|
||||
wsRemoteEndpoint.writeTimeout=Blocking write timeout
|
||||
wsRemoteEndpoint.wrongState=The remote endpoint was in state [{0}] which is an invalid state for called method
|
||||
|
||||
# Note the following message is used as a close reason in a WebSocket control
|
||||
# frame and therefore must be 123 bytes (not characters) or less in length.
|
||||
# Messages are encoded using UTF-8 where a single character may be encoded in
|
||||
# as many as 4 bytes.
|
||||
wsSession.timeout=The WebSocket session [{0}] timeout expired
|
||||
|
||||
wsSession.closed=The WebSocket session [{0}] has been closed and no method (apart from close()) may be called on a closed session
|
||||
wsSession.created=Created WebSocket session [{0}]
|
||||
wsSession.doClose=Closing WebSocket session [{0}]
|
||||
wsSession.duplicateHandlerBinary=A binary message handler has already been configured
|
||||
wsSession.duplicateHandlerPong=A pong message handler has already been configured
|
||||
wsSession.duplicateHandlerText=A text message handler has already been configured
|
||||
wsSession.flushFailOnClose=Failed to flush batched messages on session close
|
||||
wsSession.instanceNew=Endpoint instance registration failed
|
||||
wsSession.invalidHandlerTypePong=A pong message handler must implement MessageHandler.Whole
|
||||
wsSession.messageFailed=Unable to write the complete message as the WebSocket connection has been closed
|
||||
wsSession.removeHandlerFailed=Unable to remove the handler [{0}] as it was not registered with this session
|
||||
wsSession.sendCloseFail=Failed to send close message for session [{0}] to remote endpoint
|
||||
wsSession.unknownHandler=Unable to add the message handler [{0}] as it was for the unrecognised type [{1}]
|
||||
wsSession.unknownHandlerType=Unable to add the message handler [{0}] as it was wrapped as the unrecognised type [{1}]
|
||||
|
||||
# Note the following message is used as a close reason in a WebSocket control
|
||||
# frame and therefore must be 123 bytes (not characters) or less in length.
|
||||
# Messages are encoded using UTF-8 where a single character may be encoded in
|
||||
# as many as 4 bytes.
|
||||
wsWebSocketContainer.shutdown=The web application is stopping
|
||||
|
||||
wsWebSocketContainer.asynchronousSocketChannelFail=Unable to open a connection to the server
|
||||
wsWebSocketContainer.defaultConfiguratorFail=Failed to create the default configurator
|
||||
wsWebSocketContainer.endpointCreateFail=Failed to create a local endpoint of type [{0}]
|
||||
wsWebSocketContainer.failedAuthentication=Failed to handle HTTP response code [{0}]. Authentication header was not accepted by server.
|
||||
wsWebSocketContainer.httpRequestFailed=The HTTP request to initiate the WebSocket connection failed
|
||||
wsWebSocketContainer.invalidExtensionParameters=The server responded with extension parameters the client is unable to support
|
||||
wsWebSocketContainer.invalidHeader=Unable to parse HTTP header as no colon is present to delimit header name and header value in [{0}]. The header has been skipped.
|
||||
wsWebSocketContainer.invalidStatus=The HTTP response from the server [{0}] did not permit the HTTP upgrade to WebSocket
|
||||
wsWebSocketContainer.invalidSubProtocol=The WebSocket server returned multiple values for the Sec-WebSocket-Protocol header
|
||||
wsWebSocketContainer.maxBuffer=This implementation limits the maximum size of a buffer to Integer.MAX_VALUE
|
||||
wsWebSocketContainer.missingAnnotation=Cannot use POJO class [{0}] as it is not annotated with @ClientEndpoint
|
||||
wsWebSocketContainer.missingLocationHeader=Failed to handle HTTP response code [{0}]. Missing Location header in response
|
||||
wsWebSocketContainer.missingWWWAuthenticateHeader=Failed to handle HTTP response code [{0}]. Missing WWW-Authenticate header in response
|
||||
wsWebSocketContainer.pathNoHost=No host was specified in URI
|
||||
wsWebSocketContainer.pathWrongScheme=The scheme [{0}] is not supported. The supported schemes are ws and wss
|
||||
wsWebSocketContainer.proxyConnectFail=Failed to connect to the configured Proxy [{0}]. The HTTP response code was [{1}]
|
||||
wsWebSocketContainer.redirectThreshold=Cyclic Location header [{0}] detected / reached max number of redirects [{1}] of max [{2}]
|
||||
wsWebSocketContainer.sessionCloseFail=Session with ID [{0}] did not close cleanly
|
||||
wsWebSocketContainer.sslEngineFail=Unable to create SSLEngine to support SSL/TLS connections
|
||||
wsWebSocketContainer.unsupportedAuthScheme=Failed to handle HTTP response code [{0}]. Unsupported Authentication scheme [{1}] returned in response
|
||||
36
java/org/apache/tomcat/websocket/LocalStrings_de.properties
Normal file
36
java/org/apache/tomcat/websocket/LocalStrings_de.properties
Normal file
@@ -0,0 +1,36 @@
|
||||
# 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.
|
||||
|
||||
caseInsensitiveKeyMap.nullKey=Null Schlüssel sind nicht erlaubt
|
||||
|
||||
wsFrame.closed=Weiterer Frame empfangen nachdem bereits ein Kontroll Frame vom Typ Close empfangen wurde
|
||||
wsFrame.illegalReadState=Unerwarteter Lesestatus [{0}]
|
||||
wsFrame.wrongRsv=Der Client Frame setzt die reservierten Bits auf [{0}] für eine Nachricht mit dem opCode [{1}], der von diesem Endpunkt nicht unterstüzt wird
|
||||
|
||||
wsHandshakeRequest.invalidUri=Aus dem String [{0}] kann keine valide URI konstruiert werden
|
||||
|
||||
wsRemoteEndpoint.closedDuringMessage=Der Rest der Message wird nicht gesendet werden, da die WebSocket Session bereits beendet wurde
|
||||
wsRemoteEndpoint.tooMuchData=Ping oder Pong darf nicht mehr als 125 Bytes senden
|
||||
wsRemoteEndpoint.wrongState=Der entfernte Endpunkt war im Zustand [{0}] welcher für die aufgerufene Methode ungültig ist
|
||||
|
||||
wsSession.created=Websocket Sitzung [{0}] erzeugt
|
||||
wsSession.doClose=Schließe WebSocket-Sitzung [{1}]
|
||||
wsSession.duplicateHandlerText=Ein Text Message Handler ist bereits konfiguriert
|
||||
wsSession.instanceNew=Registrierung der Endpunkt-Instanz ist fehlgeschlagen
|
||||
|
||||
wsWebSocketContainer.asynchronousSocketChannelFail=Es kann keine Verbindung zum Server hergestellt werden
|
||||
wsWebSocketContainer.missingAnnotation=Die POJO Klasse [{0}] kann nicht verwendet werden da sie nicht mit @ClientEndpoint annotiert ist.
|
||||
wsWebSocketContainer.pathNoHost=In der URI wurde kein Host angegeben
|
||||
wsWebSocketContainer.sessionCloseFail=Die Sitzung mit der ID [{0}] wurde nicht sauber geschlossen.
|
||||
45
java/org/apache/tomcat/websocket/LocalStrings_es.properties
Normal file
45
java/org/apache/tomcat/websocket/LocalStrings_es.properties
Normal file
@@ -0,0 +1,45 @@
|
||||
# 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.
|
||||
|
||||
caseInsensitiveKeyMap.nullKey=No se permiten llaves nulas (Null)
|
||||
|
||||
perMessageDeflate.duplicateParameter=La definición del parámetro de extención [{0}] esta duplicada
|
||||
perMessageDeflate.invalidWindowSize=Una ventana inválida de tamaño [{1}] fue especificada para [{0}]. Los valores válidos son números entre 8 y 15 incluyendo los extremos.
|
||||
|
||||
util.notToken=Un parámetro con extención ilegal fue especificado con nombre [{0}] y valor [{1}]
|
||||
util.unknownDecoderType=No se reconoce el decodificador tipo [{0}]
|
||||
|
||||
wsFrame.closed=Nuevo cuadro recibido luego de cerrar el cuadro de control
|
||||
wsFrame.notMasked=El cuadro del cliente no fue enmascarado, pero todos los cuadros de clientes deben ser enmascarados
|
||||
wsFrame.wrongRsv=El rango del cliente fija los bits reservados a [{0}] para un mensaje con opCode [{1}] el cual no fue soportado por este endpoint\n
|
||||
|
||||
wsHandshakeRequest.invalidUri=La cadena [{0}] no puede ser usada para construir una URI válida
|
||||
|
||||
wsRemoteEndpoint.closed=El mensaje no será enviado porque la sesión WebSocket ha sido cerrada
|
||||
wsRemoteEndpoint.closedDuringMessage=No se enviara el resto del mensaje debido a que la sesión WebSocket esta cerrada
|
||||
wsRemoteEndpoint.flushOnCloseFailed=Los mensages de lote estan habilitados aún después de haberse cerrado la sesión. Imposible descartar los messages de lote restantes.
|
||||
wsRemoteEndpoint.sendInterrupt=El hilo actual fue interrumpido mientras esperaba que se completara un envio de bloqueo
|
||||
wsRemoteEndpoint.tooMuchData=Ping o pong no pueden enviar más de 125 bytes
|
||||
wsRemoteEndpoint.wrongState=El endpoint remoto estaba en estado [{0}] el cual es un estado no válido para el método llamado
|
||||
|
||||
wsSession.closed=La sesión WebSocket [{0}] ha sido cerrada y ningún otro método (aparte de close()) puede ser llamado en una sesión cerrada\n
|
||||
wsSession.created=La sesion WebSocket [{0}] fue creada\n
|
||||
wsSession.doClose=Cerrando WebSocket sesión [{1}]
|
||||
wsSession.duplicateHandlerText=Un manejador de mensaje de texto ya ha sido configurado
|
||||
wsSession.instanceNew=Falló la registración de la instancia del dispoitivo final
|
||||
|
||||
wsWebSocketContainer.missingWWWAuthenticateHeader=Fallo al manejar el código de respuesta HTTP [{0}]. No existe la cabecera WWW-Authenticate en la respuesta
|
||||
wsWebSocketContainer.pathNoHost=No se especificó ningún host en URI
|
||||
wsWebSocketContainer.sessionCloseFail=La sesión con ID [{0}] no se cerró correctamente
|
||||
131
java/org/apache/tomcat/websocket/LocalStrings_fr.properties
Normal file
131
java/org/apache/tomcat/websocket/LocalStrings_fr.properties
Normal file
@@ -0,0 +1,131 @@
|
||||
# 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.
|
||||
|
||||
asyncChannelGroup.createFail=Impossible de créer un AsynchronousChannelGroup dédié poour les clients Websockets ce qui est nécessaire pour éviter des fuites de mémoire dans un conteneur EE
|
||||
|
||||
asyncChannelWrapperSecure.check.notOk=La négociation TLS a renvoyé un état inattendu [{0}]
|
||||
asyncChannelWrapperSecure.check.unwrap=Des octets ont été écrits sur la sortie pendant la lecture
|
||||
asyncChannelWrapperSecure.check.wrap=Des octets ont été consommés depuis l'entrée lors d'une écriture
|
||||
asyncChannelWrapperSecure.closeFail=Impossible de fermer proprement le canal
|
||||
asyncChannelWrapperSecure.concurrentRead=Les opérations de lecture concurrentes ne sont pas permises
|
||||
asyncChannelWrapperSecure.concurrentWrite=Les opérations d'écriture concurrentes ne sont pas permises
|
||||
asyncChannelWrapperSecure.eof=Fin de flux inattendue
|
||||
asyncChannelWrapperSecure.notHandshaking=Etat NOT_HANDSHAKING inattendu pendant la négociation TLS
|
||||
asyncChannelWrapperSecure.statusUnwrap=Etat inattendu de SSLEngineResult après une opération unwrap()
|
||||
asyncChannelWrapperSecure.statusWrap=Etat inattendu de SSLEngineResult après une opération wrap()
|
||||
asyncChannelWrapperSecure.tooBig=Le résultat [{0}] est trop grand pour pouvoir être converti en Integer
|
||||
asyncChannelWrapperSecure.wrongStateRead=L'indicateur de lecture en cours était faux alors qu'il aurait dû vrai lors d'une tentative pour terminer une opération de lecture
|
||||
asyncChannelWrapperSecure.wrongStateWrite=L'indicateur d'écriture en cours était faux alors qu'il aurait dû vrai lors d'une tentative pour terminer une opération d'écriture
|
||||
|
||||
backgroundProcessManager.processFailed=Un processus d'arrière-plan a échoué
|
||||
|
||||
caseInsensitiveKeyMap.nullKey=Les clés nulles ne sont pas admises
|
||||
|
||||
futureToSendHandler.timeout=Le délai d''attente de l''opération est dépassé après avoir attendu [{0}] [{1}] pour qu''elle se termine
|
||||
|
||||
perMessageDeflate.deflateFailed=Impossible de décompresser une trame WebSocket compressée
|
||||
perMessageDeflate.duplicateParameter=Double définition pour le paramètre d''extension [{0}]
|
||||
perMessageDeflate.invalidState=Etat invalide
|
||||
perMessageDeflate.invalidWindowSize=Une taille [{1}] de fenêtre invalide a été spécifiée pour [{0}], les valeurs valides sont les entiers de 8 à 15 inclus
|
||||
perMessageDeflate.unknownParameter=Un paramètre d''extension inconnu [{0}] a été défini
|
||||
|
||||
transformerFactory.unsupportedExtension=L''extension [{0}] n''est pas supportée
|
||||
|
||||
util.invalidMessageHandler=Le gestionnaire de messages fourni n'a pas de méthode onMessage(Object)
|
||||
util.invalidType=Incapable de convertir la valeur [{0}] en le type [{1}]. Ce type n''est pas supporté.
|
||||
util.notToken=Un paramètre d''extension illégal a été spécifié avec le nom [{0}] et la valeur [{1}]
|
||||
util.unknownDecoderType=Le Decoder de type [{0}] n''est pas reconnu
|
||||
|
||||
wsFrame.alreadyResumed=Le message reçu a déjà été suspendu puis recommencé
|
||||
wsFrame.alreadySuspended=La réception des messages a déjà été suspendue
|
||||
wsFrame.bufferTooSmall=Le tampon de taille [{0}] est trop petit pour le message de taille [{1}] et les messages asynchrones ne sont pas supportés
|
||||
wsFrame.byteToLongFail=trop d''octets fournis ([{0}]) pour une conversion vers "long"
|
||||
wsFrame.closed=Une nouvelle trame (frame) a été reçue après une trame de contrôle de fermeture
|
||||
wsFrame.controlFragmented=Une trame de contrôle fragmentée a été reçue mais les trames de contrôle ne peuvent pas être fragmentées
|
||||
wsFrame.controlNoFin=Une trame de contrôle qui a été envoyée n'avait pas le bit fin mis, alors qu'elles ne peuvent pas utiliser de trame de continuation
|
||||
wsFrame.controlPayloadTooBig=Une trame de contrôle a été envoyée avec des données de taille [{0}] ce qui est supérieur aux 125 octets autorisés au maximum
|
||||
wsFrame.illegalReadState=Etat en lecture inattendu [{0}]
|
||||
wsFrame.invalidOpCode=Une trame a été envoyée avec un opCode non reconnu [{0}]
|
||||
wsFrame.invalidUtf8=Une trame texte Websocket a été reçue et n'a pu 6etre traitée car elle contenait des séquence d'octets UTF-8 invalides
|
||||
wsFrame.invalidUtf8Close=Une trame de fermeture Websocket a été reçue avec une cause qui contenait des séquences UTF-8 invalides
|
||||
wsFrame.ioeTriggeredClose=Une IOException non récupérable est survenue donc la connection a été fermée
|
||||
wsFrame.messageTooBig=Le message fait [{0}] octets mais le MessageHandler a une limite de [{1}] octets
|
||||
wsFrame.noContinuation=Un nouveau message a été démarré quand une trame de continuation était attendue
|
||||
wsFrame.notMasked=La trame du client n'a pas de masque alors que toutes les trames des clients doivent en avoir un
|
||||
wsFrame.oneByteCloseCode=Le client a envoyé une trame de fermeture avec un octet de données ce qui est invalide
|
||||
wsFrame.partialHeaderComplete=Une trame Websocket a été recue, fin [{0}], rsv [{1}], opCode [{2}], taille de données [{3}]
|
||||
wsFrame.sessionClosed=Les données du client ne peuvent pas être traitées car la session a déjà été fermée
|
||||
wsFrame.suspendRequested=La suspension de la réception des messages a déjà été demandée
|
||||
wsFrame.textMessageTooBig=Le message texte décodé était trop grand pour le tampon de sortie et la terminaison ne supporte pas les messages partiels
|
||||
wsFrame.wrongRsv=La trame cliente (client frame) a les bits réservés d''un message dont l''opCode est [{1}] définis à [{0}], et ce n''est pas supporté par cette terminaison
|
||||
|
||||
wsFrameClient.ioe=Echec lors de la lecture des données envoyées par le serveur
|
||||
|
||||
wsHandshakeRequest.invalidUri=La chaîne de caractères [{0}] ne peut être utilisée pour construire un URL valide
|
||||
wsHandshakeRequest.unknownScheme=Le schéma [{0}] de la requête n''est pas reconnu
|
||||
|
||||
wsRemoteEndpoint.acquireTimeout=Le message en cours n'a pas été complètement envoyé dans le délai imparti
|
||||
wsRemoteEndpoint.changeType=Quand un message fragmenté est envoyé, tous les fragments doivent être de même type
|
||||
wsRemoteEndpoint.closed=Le message ne sera pas envoyé parce que la session WebSocket a été fermée
|
||||
wsRemoteEndpoint.closedDuringMessage=Le reste du message ne sera pas envoyé parce que la session WebSocket est déjà fermée.
|
||||
wsRemoteEndpoint.closedOutputStream=La méthode ne peut pas être appelée alors que l'OutputStream a été fermée
|
||||
wsRemoteEndpoint.closedWriter=Cette méthode ne doit pas être appelée car le Writer a été fermé
|
||||
wsRemoteEndpoint.flushOnCloseFailed=Le groupement de messages est toujours actif après fermeture de la session, impossible d'envoyer les messages restants
|
||||
wsRemoteEndpoint.invalidEncoder=L''encodeur spécifié de type [{0}] n''a pu être instancié
|
||||
wsRemoteEndpoint.noEncoder=Pas d''encodeur spécifié pour un objet de classe [{0}]
|
||||
wsRemoteEndpoint.nullData=Argument nul invalide.
|
||||
wsRemoteEndpoint.nullHandler=Argument null invalide pour le gestionnaire
|
||||
wsRemoteEndpoint.sendInterrupt=Le thread actuel a été interrompu alors qu'il attendait qu'un envoi bloquant ne se termine
|
||||
wsRemoteEndpoint.tooMuchData=Un ping ou pong ne peut pas envoyer plus de 125 octets
|
||||
wsRemoteEndpoint.writeTimeout=Délai d'attente dépassé pour l'écriture bloquante
|
||||
wsRemoteEndpoint.wrongState=La terminaison distante est dans l''état [{0}] ce qui est invalide pour la méthode appelée
|
||||
|
||||
wsSession.closed=La session WebSocket [{0}] a été fermée et aucune méthode (à part close()) ne peut être appelée sur une session fermée
|
||||
wsSession.created=Création de la session WebSocket [{0}]
|
||||
wsSession.doClose=Fermeture de la session WebSocket [{1}]
|
||||
wsSession.duplicateHandlerBinary=Un gestionnaire de message binaire a déjà été configuré
|
||||
wsSession.duplicateHandlerPong=Un gestionnaire de messages pong a déjà été configuré
|
||||
wsSession.duplicateHandlerText=Un gestionnaire de message texte a déjà été configuré
|
||||
wsSession.flushFailOnClose=Impossible d'envoyer la file de messages lors de la fermeture de la session
|
||||
wsSession.instanceNew=L'enregistrement de l'instance de la terminaison a échoué
|
||||
wsSession.invalidHandlerTypePong=Un gestionnaire de message pong doit implémenter MessageHandler.Whole
|
||||
wsSession.messageFailed=Impossible d'écrire le message WebSocket complet car la connection a été fermée
|
||||
wsSession.removeHandlerFailed=Impossible d''enlever le gestionnaire [{0}] car il n''était pas enregistré dans la session
|
||||
wsSession.sendCloseFail=Impossible d''envoyer le message de fermeture pour la session [{0}] à la terminaison distante
|
||||
wsSession.timeout=Le délai d''attente maximum de la session WebSocket [{0}] a été dépassé
|
||||
wsSession.unknownHandler=Impossible d''ajouter le gestionnaire de messages [{0}] pour le type non reconnu [{1}]
|
||||
wsSession.unknownHandlerType=Incapable d''ajouter le gestionnaire de messages [{0}] puisqu''il est enveloppé (wrapped) comme le type non reconnu [{1}]
|
||||
|
||||
wsWebSocketContainer.asynchronousSocketChannelFail=Impossible d'ouvrir une connection vers le serveur
|
||||
wsWebSocketContainer.defaultConfiguratorFail=Impossible de créer le configurateur par défaut
|
||||
wsWebSocketContainer.endpointCreateFail=Echec de création d''un point d''entrée local de type [{0}]
|
||||
wsWebSocketContainer.failedAuthentication=Echec du traitement du code de réponse HTTP [{0}], l''en-tête d''authentification n''a pas été accepté par le serveur
|
||||
wsWebSocketContainer.httpRequestFailed=La requête HTTP pour initier la connection WebSocket a échoué
|
||||
wsWebSocketContainer.invalidExtensionParameters=Le serveur a répondu avec des paramètres d'extension que le client n'est pas capable de traiter
|
||||
wsWebSocketContainer.invalidHeader=Impossible de traiter l''en-tête HTTP car deux-points n''est pas présents pour délimiter le nom et la valeur dans [{0}], l''en-tête a été sauté
|
||||
wsWebSocketContainer.invalidStatus=La réponse HTTP du serveur [{0}] n''a pas permis une mise à niveau de HTTP vers WebSocket
|
||||
wsWebSocketContainer.invalidSubProtocol=Le serveur WebSocket a renvoyé plusieurs valeurs pour l'en-tête Sec-WebSocket-Protocol
|
||||
wsWebSocketContainer.maxBuffer=L'implémentation limites la valeur maximale d'un tampon à Integer.MAX_VALUE
|
||||
wsWebSocketContainer.missingAnnotation=Impossible d''utiliser la classe POJO [{0}] car elle n''est pas annotée avec @ClientEndpoint
|
||||
wsWebSocketContainer.missingLocationHeader=Echec du traitement du code de réponse HTTP [{0}], l''en-tête location n''est pas présent dans la réponse
|
||||
wsWebSocketContainer.missingWWWAuthenticateHeader=Echec de traitement du code HTTP de réponse [{0}] : la réponse ne contient pas de header WWW-Authenticate.
|
||||
wsWebSocketContainer.pathNoHost=Aucun hôte n'est spécifié dans l'URI
|
||||
wsWebSocketContainer.pathWrongScheme=Le schéma [{0}] n''est pas supporté, seuls sont supportés ws et wss
|
||||
wsWebSocketContainer.proxyConnectFail=Impossible de se connecter au Proxy [{0}] configuré, le code HTTP de la réponse est [{0}]
|
||||
wsWebSocketContainer.redirectThreshold=L''en-tête Location [{0}] est cyclique, le nombre de redirections [{1}] a été atteint sur le maximum [{2}]
|
||||
wsWebSocketContainer.sessionCloseFail=La session avec ID [{0}] n''a pas été fermée proprement.
|
||||
wsWebSocketContainer.shutdown=L'application web s'arrête
|
||||
wsWebSocketContainer.sslEngineFail=Impossible de créer un SSLEngine pour supporter les connections TLS
|
||||
wsWebSocketContainer.unsupportedAuthScheme=Impossible de gérer le code de réponse HTTP [{0}], un schéma authentification [{1}] non supporté a été retourné
|
||||
131
java/org/apache/tomcat/websocket/LocalStrings_ja.properties
Normal file
131
java/org/apache/tomcat/websocket/LocalStrings_ja.properties
Normal file
@@ -0,0 +1,131 @@
|
||||
# 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.
|
||||
|
||||
asyncChannelGroup.createFail=JavaEEコンテナなどの複雑なクラスローダ環境でメモリリークを防ぐために必要なWebSocketクライアント専用のAsynchronousChannelGroupを作成できません
|
||||
|
||||
asyncChannelWrapperSecure.check.notOk=TLSハンドシェイクが予期しないステータスを返しました[{0}]
|
||||
asyncChannelWrapperSecure.check.unwrap=読み込み中にバイトが出力に書き込まれました。
|
||||
asyncChannelWrapperSecure.check.wrap=書き込み中に入力からバイトが消費されました。
|
||||
asyncChannelWrapperSecure.closeFail=チャンネルをきれいに閉じることができませんでした
|
||||
asyncChannelWrapperSecure.concurrentRead=コンカレントな読み取り操作を行うことはできません。
|
||||
asyncChannelWrapperSecure.concurrentWrite=コンカレントな書き込み操作を行うことはできません。
|
||||
asyncChannelWrapperSecure.eof=予期せぬ位置にストリームの終端を検出しました。
|
||||
asyncChannelWrapperSecure.notHandshaking=TLSハンドシェイク中に予期しない状態[NOT_HANDSHAKING]
|
||||
asyncChannelWrapperSecure.statusUnwrap=unwrap()操作後のSSLEngineResultの予期しないステータス
|
||||
asyncChannelWrapperSecure.statusWrap=wrap()操作後のSSLEngineResultの予期しないステータス。
|
||||
asyncChannelWrapperSecure.tooBig=Integer として解釈するには大きすぎる結果 [{0}] です。
|
||||
asyncChannelWrapperSecure.wrongStateRead=読み取り操作の完了中に読み取り中を意味するフラグが false になっていることを検出しました (true になっているべきです)。
|
||||
asyncChannelWrapperSecure.wrongStateWrite=書き込み操作を完了しようとすると、書き込みが進行中であることを示すフラグがfalse(trueであったはずです)であることが判明しました。
|
||||
|
||||
backgroundProcessManager.processFailed=バックグラウンド処理が失敗しました。
|
||||
|
||||
caseInsensitiveKeyMap.nullKey=null 値はキーに使用できません。
|
||||
|
||||
futureToSendHandler.timeout=[{0}] [{1}]を完了するのを待ってから操作がタイムアウトしました
|
||||
|
||||
perMessageDeflate.deflateFailed=圧縮された WebSocket フレームを展開できません。
|
||||
perMessageDeflate.duplicateParameter=[{0}]拡張パラメータの重複した定義
|
||||
perMessageDeflate.invalidState=不正な状態です。
|
||||
perMessageDeflate.invalidWindowSize=[{0}] のウインドウサイズに不正な値 [{1}] が指定されました。ウインドウサイズは 8 より大きく 15 未満でなければなりません。
|
||||
perMessageDeflate.unknownParameter=未知の拡張パラメーター [{0}] が指定されました。
|
||||
|
||||
transformerFactory.unsupportedExtension=未対応の拡張 [{0}] です。
|
||||
|
||||
util.invalidMessageHandler=提供されたメッセージハンドラにonMessage(Object)メソッドがありません
|
||||
util.invalidType=値[{0}]をタイプ[{1}]に強制できません。 このタイプはサポートされていません。
|
||||
util.notToken=パラメーター名 [{0}]、値 [{1}] の不正な拡張パラメーターが指定されました。
|
||||
util.unknownDecoderType=デコーダタイプ[{0}]は認識されません
|
||||
|
||||
wsFrame.alreadyResumed=メッセージの受信は既に再開されています。
|
||||
wsFrame.alreadySuspended=メッセージの受信は既に中断されています。
|
||||
wsFrame.bufferTooSmall=非同期メッセージの非サポートとバッファーが小さすぎます。 バッファサイズ:[{0}]、メッセージサイズ:[{1}]
|
||||
wsFrame.byteToLongFail=long へ変換するために巨大なバイト列 ([{0}]) が指定されました。
|
||||
wsFrame.closed=閉じたコントローフレームで新しいデータフレームを受信しました。
|
||||
wsFrame.controlFragmented=断片化されたコントロールフレームが受信されましたが、コントロールフレームは断片化されません。
|
||||
wsFrame.controlNoFin=fin ビットがオフになっているコントロールフレームを受信しました。コントロールフレームを継続フレームとして使用することはできません。
|
||||
wsFrame.controlPayloadTooBig=コントロールフレームは [{0}] バイトのペイロードで送信されましたが、送信可能な最大値の 125 バイトを越えています。
|
||||
wsFrame.illegalReadState=予期しない読み取り状態[{0}]
|
||||
wsFrame.invalidOpCode=未知の opCode [{0}] の WebSocket フレームを受信しました。
|
||||
wsFrame.invalidUtf8=無効なバイトシーケンスが含まれていたため、UTF-8にデコードできなかったWebSocketテキストフレームが受信されました。
|
||||
wsFrame.invalidUtf8Close=WebSocket は不正な UTF-8 バイト列を含むことを原因とするクローズフレームを受信しました。
|
||||
wsFrame.ioeTriggeredClose=回復不能なIOException が発生したためコネクションを切断します。
|
||||
wsFrame.messageTooBig=メッセージは[{0}]バイトの長さでしたが、MessageHandlerには[{1}]バイトの制限があります。
|
||||
wsFrame.noContinuation=continuation フレームが予想されたときに新しいメッセージが開始されました。
|
||||
wsFrame.notMasked=クライアントのフレームはマスクされていませんが、全てのクライアントのフレームはマスクしなければなりません。
|
||||
wsFrame.oneByteCloseCode=クライアントは有効ではない単一バイトのペイロードを含むクローズフレームを送信しました。
|
||||
wsFrame.partialHeaderComplete=WebSocket フレームを受信しました。fin [{0}]、rsv [{1}]、OpCode [{2}]、ペイロード長 [{3}]
|
||||
wsFrame.sessionClosed=セッションが既に閉じられているため、クライアントデータを処理できません。
|
||||
wsFrame.suspendRequested=すでにメッセージの受信中断を要求しています。
|
||||
wsFrame.textMessageTooBig=デコードされたテキストメッセージが出力バッファにとって大きすぎます。さらにエンドポイントが部分メッセージをサポートしていません。
|
||||
wsFrame.wrongRsv=クライアントフレームは opCode [{1}] でメッセージを送信するため [{0}] の予約ビットを設定しましたが、エンドポイントは対応していません。
|
||||
|
||||
wsFrameClient.ioe=サーバーから送信されたデータを読み取る際にエラーが発生しました。
|
||||
|
||||
wsHandshakeRequest.invalidUri=文字列 [{0}] は正常な URI に含めることができません。
|
||||
wsHandshakeRequest.unknownScheme=リクエストのスキーム[{0}]が認識されません
|
||||
|
||||
wsRemoteEndpoint.acquireTimeout=指定した時間内にメッセージを送信できませんでした。
|
||||
wsRemoteEndpoint.changeType=フラグメント化されたメッセージを送信する場合、すべてのフラグメントは同じタイプでなければなりません。
|
||||
wsRemoteEndpoint.closed=WebSocket セッションは切断済みのためメッセージを送信しません。
|
||||
wsRemoteEndpoint.closedDuringMessage=WebSocket セッションが切断されているため残りのメッセージは送信できません。
|
||||
wsRemoteEndpoint.closedOutputStream=このメソッドは、OutputStreamが閉じられたときに呼び出されない場合があります。
|
||||
wsRemoteEndpoint.closedWriter=Writerがクローズされているため、このメソッドを呼び出すことはできません。
|
||||
wsRemoteEndpoint.flushOnCloseFailed=セッションが閉じられた後にまだ可能であったバッチメッセージ。 残りのバッチメッセージをフラッシュできません。
|
||||
wsRemoteEndpoint.invalidEncoder=指定されたタイプ[{0}]のエンコーダをインスタンス化できませんでした。
|
||||
wsRemoteEndpoint.noEncoder=クラス [{0}] のオブジェクトのエンコーダーが未指定です。
|
||||
wsRemoteEndpoint.nullData=無効なNullデータ引数
|
||||
wsRemoteEndpoint.nullHandler=無効なnullハンドラ引数
|
||||
wsRemoteEndpoint.sendInterrupt=同期送信の完了待ちスレッドに割り込みが発生しました。
|
||||
wsRemoteEndpoint.tooMuchData=Ping および Pong は 125 バイト以上送信できません。
|
||||
wsRemoteEndpoint.writeTimeout=ブロッキング書き込みのタイムアウト
|
||||
wsRemoteEndpoint.wrongState=リモートエンドポイントの状態 [{0}] は呼び出したメソッドに対して不正な状態です。
|
||||
|
||||
wsSession.closed=WebSocket セッション [{0}] を切断しました。切断済みのセッションに close() 以外のメソッド呼び出しをすることはありません。
|
||||
wsSession.created=WebSocket セッション [{0}] を作成しました。
|
||||
wsSession.doClose=WebSocket セッション [{1}] を切断します。
|
||||
wsSession.duplicateHandlerBinary=バイナリメッセージハンドラは既に設定されています。
|
||||
wsSession.duplicateHandlerPong=pongメッセージハンドラは既に設定されています。
|
||||
wsSession.duplicateHandlerText=テキストメッセージハンドラはすでに構成されています。
|
||||
wsSession.flushFailOnClose=セッション切断時にバッチメッセージをフラッシュできませんでした。
|
||||
wsSession.instanceNew=エンドポイントインスタンスの登録に失敗しました。
|
||||
wsSession.invalidHandlerTypePong=pongメッセージハンドラはMessageHandler.Wholeを実装する必要があります。
|
||||
wsSession.messageFailed=WebSocket コネクションが切断されているため、完了メッセージを送信できません。
|
||||
wsSession.removeHandlerFailed=セッションに登録されていないためハンドラー [{0}] を解除できません。
|
||||
wsSession.sendCloseFail=セッション[{0}]のクローズメッセージをリモートエンドポイントに送信できませんでした。
|
||||
wsSession.timeout=WebSocketセッション[{0}]タイムアウトが切れました。
|
||||
wsSession.unknownHandler=認識できないタイプ[{1}]のメッセージハンドラ[{0}]を追加できません。
|
||||
wsSession.unknownHandlerType=認識できない型[{1}]としてラップされたメッセージハンドラ[{0}]を追加できません。
|
||||
|
||||
wsWebSocketContainer.asynchronousSocketChannelFail=サーバーへの接続を開始できません。
|
||||
wsWebSocketContainer.defaultConfiguratorFail=デフォルトコンフィグレータの作成に失敗しました。
|
||||
wsWebSocketContainer.endpointCreateFail=クラス [{0}] のローカルエンドポイントを作成できません。
|
||||
wsWebSocketContainer.failedAuthentication=HTTP応答コード[{0}]を処理できませんでした。 認証ヘッダーがサーバーによって受け入れられませんでした。
|
||||
wsWebSocketContainer.httpRequestFailed=WebSocket接続を開始するHTTPリクエストが失敗しました。
|
||||
wsWebSocketContainer.invalidExtensionParameters=サーバーはクライアントの解釈できない拡張パラメーターで応答しました。
|
||||
wsWebSocketContainer.invalidHeader=ヘッダー名と値の区切り文字(コロン)がない HTTP ヘッダー [{0}] は解釈できないため無視します。
|
||||
wsWebSocketContainer.invalidStatus=サーバー[{0}]からのHTTPレスポンスがWebSocketへのHTTPアップグレードを許可しませんでした。
|
||||
wsWebSocketContainer.invalidSubProtocol=WebSocketサーバーは、Sec-WebSocket-Protocolヘッダーに複数の値を返しました。
|
||||
wsWebSocketContainer.maxBuffer=この実装はバッファの最大サイズをInteger.MAX_VALUEに制限します。
|
||||
wsWebSocketContainer.missingAnnotation=POJOクラス[{0}]は@ClientEndpointでアノテーションされていないため使用できません。
|
||||
wsWebSocketContainer.missingLocationHeader=HTTP レスポンスコード [{0}] を処理できません。レスポンスに Location ヘッダーがありませんでした。
|
||||
wsWebSocketContainer.missingWWWAuthenticateHeader=HTTP 応答コード [{0}] を処理できません。応答ヘッダーに WWW-Authenticate ヘッダーがありません。
|
||||
wsWebSocketContainer.pathNoHost=URIにホストが指定されていません
|
||||
wsWebSocketContainer.pathWrongScheme=スキーマ[{0}]はサポートされていません。 サポートされているスキーマはwsとwssです
|
||||
wsWebSocketContainer.proxyConnectFail=設定されたプロキシ[{0}]に接続できませんでした。 HTTPレスポンスコードは[{1}]でした。
|
||||
wsWebSocketContainer.redirectThreshold=Locationヘッダー [{0}] の循環を検出、リダイレクト回数 [{1}] が上限値 [{2}] を超過しました。
|
||||
wsWebSocketContainer.sessionCloseFail=ID [{0}] のセッションは正常に切断しませんでした。
|
||||
wsWebSocketContainer.shutdown=Webアプリケーションは停止中です
|
||||
wsWebSocketContainer.sslEngineFail=SSL/TLS 接続のための SSL エンジンを作成できません。
|
||||
wsWebSocketContainer.unsupportedAuthScheme=HTTPレスポンスコード[{0}]を処理できませんでした。 サポートされていない認証スキーム[{1}]がレスポンスで返されました。
|
||||
131
java/org/apache/tomcat/websocket/LocalStrings_ko.properties
Normal file
131
java/org/apache/tomcat/websocket/LocalStrings_ko.properties
Normal file
@@ -0,0 +1,131 @@
|
||||
# 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.
|
||||
|
||||
asyncChannelGroup.createFail=JavaEE 컨테이너들과 같은 복잡한 클래스로더 환경에서 메모리 누수를 방지하기 위해 필수적이며 웹소켓 클라이언트들을 위한, 전용 AsynchronousChannelGroup를 생성할 수 없습니다.
|
||||
|
||||
asyncChannelWrapperSecure.check.notOk=TLS handshake가 예기치 않은 상태값 [{0}]을(를) 반환했습니다.
|
||||
asyncChannelWrapperSecure.check.unwrap=데이터를 읽는 동안, 바이트들이 출력으로 쓰여졌습니다.
|
||||
asyncChannelWrapperSecure.check.wrap=쓰기 작업을 하는 동안, 입력으로부터 바이트들이 소비되었습니다.
|
||||
asyncChannelWrapperSecure.closeFail=채널을 깨끗하게 닫지 못했습니다.
|
||||
asyncChannelWrapperSecure.concurrentRead=동시 발생적인 읽기 오퍼레이션들은 허용되지 않습니다.
|
||||
asyncChannelWrapperSecure.concurrentWrite=동시적인 쓰기 오퍼레이션들은 허용되지 않습니다.
|
||||
asyncChannelWrapperSecure.eof=예기치 않은 스트림의 끝
|
||||
asyncChannelWrapperSecure.notHandshaking=TLS handshake 과정 중 예기치 않은 상태 [NOT_HANDSHAKING]입니다.
|
||||
asyncChannelWrapperSecure.statusUnwrap=unwrap() 오퍼레이션 후에, SSLEngineResult의 예기치 않은 상태입니다.
|
||||
asyncChannelWrapperSecure.statusWrap=wrap() 오퍼레이션 수행 이후, SSLEngineResult의 예기치 않은 상태입니다.
|
||||
asyncChannelWrapperSecure.tooBig=결과 [{0}]이(가) 너무 커서, 정수로서 표현될 수 없습니다.
|
||||
asyncChannelWrapperSecure.wrongStateRead=읽기 오퍼레이션을 완료하려 시도할 때에, 읽기 진행 중임을 표시하는 플래그가 false인 것으로 (true였어만 했음에도) 밝혀졌습니다.
|
||||
asyncChannelWrapperSecure.wrongStateWrite=쓰기 오퍼레이션을 완료하려 시도할 때, 쓰기 진행 중이라는 플래그가 false로 (true였어야 함에도) 밝혀졌습니다.
|
||||
|
||||
backgroundProcessManager.processFailed=백그라운드 프로세스가 실패했습니다.
|
||||
|
||||
caseInsensitiveKeyMap.nullKey=널인 키들은 허용되지 않습니다.
|
||||
|
||||
futureToSendHandler.timeout=[{0}] [{1}]이(가) 완료되기를 기다린 후, 작업 제한 시간을 초과했습니다.
|
||||
|
||||
perMessageDeflate.deflateFailed=압축된 웹소켓 프레임의 압축을 풀지 못했습니다.
|
||||
perMessageDeflate.duplicateParameter=[{0}] 확장 파라미터가 중복 정의되어 있습니다.
|
||||
perMessageDeflate.invalidState=유효하지 않은 상태
|
||||
perMessageDeflate.invalidWindowSize=크기가 [{1}]인 유효하지 않은 윈도우들이 [{0}]을 위해 지정되었습니다. 유효한 값들의 범위는 8에서 15까지의 모든 숫자들입니다.
|
||||
perMessageDeflate.unknownParameter=알 수 없는 확장 파라미터 [{0}]은(는), 정의되지 않았습니다.
|
||||
|
||||
transformerFactory.unsupportedExtension=Extension [{0}]은(는) 지원되지 않습니다.
|
||||
|
||||
util.invalidMessageHandler=제공된 메시지 핸들러에 onMessage(Object) 메소드가 없습니다.
|
||||
util.invalidType=[{0}] 값을 타입 [{1}](으)로 강제 변환시킬 수 없습니다. 해당 타입은 지원되지 않습니다.
|
||||
util.notToken=허용되지 않는 확장 파라미터가 지정되었습니다. 이름: [{0}], 값: [{1}].
|
||||
util.unknownDecoderType=해당 디코더 타입 [{0}]은(는) 인식되지 않습니다.
|
||||
|
||||
wsFrame.alreadyResumed=메시지 수신이 이미 재개되었습니다.
|
||||
wsFrame.alreadySuspended=메시지 수신이 이미 일시 정지되었습니다.
|
||||
wsFrame.bufferTooSmall=비동기 메시지를 지원할 수 없습니다. 버퍼가 너무 작습니다. 버퍼 크기: [{0}], 메시지 크기: [{1}]
|
||||
wsFrame.byteToLongFail=너무 많은 바이트들([{0}])이 제공되어, long으로 변환될 수 없었습니다.
|
||||
wsFrame.closed=Control 프레임을 닫은 이후에 새로운 프레임을 받았습니다.
|
||||
wsFrame.controlFragmented=단편화된(fragmented) Control 프레임을 받았지만, Control 프레임은 단편화될 수 없습니다.
|
||||
wsFrame.controlNoFin=fin 비트셋을 포함하지 않은 control 프레임이 전송되었습니다. Control 프레임들에 continuation 프레임들이 사용되는 것이 허용되지 않습니다.
|
||||
wsFrame.controlPayloadTooBig=Control 프레임이, 크기가 [{0}]인 payload와 함께 전송되었는데, 이는 최대 허용치인 125바이트를 초과합니다.
|
||||
wsFrame.illegalReadState=예기치 않은 읽기 상태: [{0}]
|
||||
wsFrame.invalidOpCode=인식되지 않는 opCode [{0}]와(과) 함께, 웹소켓 프레임이 전송되었습니다.
|
||||
wsFrame.invalidUtf8=웹소켓 텍스트 프레임을 받았는데, 유효하지 않은 바이트 시퀀스를 포함하고 있기 때문에, UTF-8로 디코딩될 수 없었습니다.
|
||||
wsFrame.invalidUtf8Close=웹소켓 닫기 프레임을 접수하였는데, 닫기 사유는 유효하지 않은 UTF-8 바이트 시퀀스들을 포함했다는 것입니다.
|
||||
wsFrame.ioeTriggeredClose=복구될 수 없는 IOException이 발생하여 연결이 닫혔습니다.
|
||||
wsFrame.messageTooBig=메시지가 [{0}] 바이트의 길이로 되어 있으나, MessageHandler는 [{1}] 바이트의 제한값을 가지고 있습니다.
|
||||
wsFrame.noContinuation=Continuation 프레임이 요구될 때에, 새로운 메시지가 시작되었습니다.
|
||||
wsFrame.notMasked=클라이언트 프레임이 마스크 되어 있지 않습니다. 모든 클라이언트 프레임들은 반드시 마스크 되어야 합니다.
|
||||
wsFrame.oneByteCloseCode=클라이언트가 단일 바이트의 payload를 가진 닫기 프레임을 보냈는데, 이는 유효하지 않습니다.
|
||||
wsFrame.partialHeaderComplete=웹소켓 프레임을 받았습니다. fin [{0}], rsv [{1}], OpCode [{2}], payload 길이 [{3}]
|
||||
wsFrame.sessionClosed=해당 세션이 이미 닫혔기 때문에, 클라이언트 데이터가 처리될 수 없습니다.
|
||||
wsFrame.suspendRequested=메시지 수신의 일시 정지가 이미 요청되었습니다.
|
||||
wsFrame.textMessageTooBig=디코드된 텍스트 메시지가 출력 버퍼에 비해 너무 크며, 해당 엔드포인트는 partial 메시지들을 지원하지 않습니다.
|
||||
wsFrame.wrongRsv=클라이언트 프레임이, opCode [{1}]을(를) 포함한 메시지를 위해, reserved 비트들을 [{0}](으)로 설정했는데, 이는 이 엔드포인트에 의해 지원되지 않습니다.
|
||||
|
||||
wsFrameClient.ioe=서버가 전송한 데이터를 읽는 중 실패
|
||||
|
||||
wsHandshakeRequest.invalidUri=문자열 [{0}]은(는) 유효한 URI를 구성하는 데 사용될 수 없습니다.
|
||||
wsHandshakeRequest.unknownScheme=요청의 스킴 [{0}]이(가) 인식되지 않는 스킴입니다.
|
||||
|
||||
wsRemoteEndpoint.acquireTimeout=지정된 제한 시간 내에, 현재 메시지가 완전히 전송되지 않았습니다.
|
||||
wsRemoteEndpoint.changeType=단편화된(fragmented) 메시지를 전송할 때, 모든 fragment들은 반드시 동일한 타입이어야 합니다.
|
||||
wsRemoteEndpoint.closed=웹소켓 세션이 이미 닫혔기 때문에, 메시지가 전달되지 않을 것입니다.
|
||||
wsRemoteEndpoint.closedDuringMessage=웹소켓 세션이 이미 닫혔기 때문에, 메시지의 나머지 부분은 전달되지 않을 것입니다.
|
||||
wsRemoteEndpoint.closedOutputStream=OutputStream이 이미 닫혀 있으므로, 이 메소드는 호출될 수 없습니다.
|
||||
wsRemoteEndpoint.closedWriter=Writer가 이미 닫혔기 때문에, 이 메소드는 호출될 수 없습니다.
|
||||
wsRemoteEndpoint.flushOnCloseFailed=세션이 이미 종료된 이후에도, 메시지들이 배치(batch)에 포함되어 있습니다. 배치에 남아있는 메시지들을 배출할 수 없습니다.
|
||||
wsRemoteEndpoint.invalidEncoder=지정된 타입 [{0}]의 Encoder의 인스턴스를 생성할 수 없었습니다.
|
||||
wsRemoteEndpoint.noEncoder=클래스 [{0}]의 객체를 위한 인코더가 지정되지 않았습니다.
|
||||
wsRemoteEndpoint.nullData=유효하지 않은 널 데이터 아규먼트
|
||||
wsRemoteEndpoint.nullHandler=유효하지 않은 널 핸들러 아규먼트
|
||||
wsRemoteEndpoint.sendInterrupt=현재 쓰레드가, blocking 전송이 완료되기를 기다리던 중 중단되었습니다.
|
||||
wsRemoteEndpoint.tooMuchData=Ping 또는 pong은 125 바이트를 초과한 데이터를 보낼 수 없습니다.
|
||||
wsRemoteEndpoint.writeTimeout=Blocking 쓰기가 제한 시간 초과되었습니다.
|
||||
wsRemoteEndpoint.wrongState=호출된 메소드에 대해, 원격 엔드포인트가 유효하지 않은 상태 [{0}]에 있습니다.
|
||||
|
||||
wsSession.closed=웹소켓 세션 [{0}]은(는) 이미 닫혔으며, (close()를 제외한) 어떤 메소드도 닫힌 세션에 호출되어서는 안됩니다.
|
||||
wsSession.created=웹소켓 세션 [{0}]을(를) 생성했습니다.
|
||||
wsSession.doClose=웹소켓 세션 [{0}]을(를) 닫습니다.
|
||||
wsSession.duplicateHandlerBinary=바이너리 메시지 핸들러가 이미 설정되었습니다.
|
||||
wsSession.duplicateHandlerPong=Pong 메시지 핸들러가 이미 설정되었습니다.
|
||||
wsSession.duplicateHandlerText=텍스트 메시지 핸들러가 이미 설정되어 있습니다.
|
||||
wsSession.flushFailOnClose=세션이 닫힐 때, 배치에 쌓인 메시지들을 배출하지 못했습니다.
|
||||
wsSession.instanceNew=엔드포인트 인스턴스 등록 실패
|
||||
wsSession.invalidHandlerTypePong=Pong 메시지 핸들러는 반드시 MessageHandler.Whole을 구현해야 합니다.
|
||||
wsSession.messageFailed=웹소켓 연결이 이미 닫혔기 때문에, 완전한 메시지를 쓸 수 없습니다.
|
||||
wsSession.removeHandlerFailed=핸들러 [{0}]이(가), 이 세션과 함께 등록되지 않았었기 때문에, 제거될 수 없습니다.
|
||||
wsSession.sendCloseFail=세션 [{0}]을(를) 위해, 원격 엔드포인트로 세션 닫기 메시지를 보내지 못했습니다.
|
||||
wsSession.timeout=웹소켓 세션 [{0}]이(가) 제한 시간 초과로 만료되었습니다.
|
||||
wsSession.unknownHandler=인식되지 않는 타입 [{1}]을(를) 위한 것이었기에, 해당 메시지 핸들러 [{0}]을(를) 추가할 수 없습니다.
|
||||
wsSession.unknownHandlerType=메시지 핸들러 [{0}]이(가) 인식되지 않는 타입 [{1}](으)로 wrap 되어 있어, 추가할 수 없습니다.
|
||||
|
||||
wsWebSocketContainer.asynchronousSocketChannelFail=서버에 대한 연결을 열 수 없습니다.
|
||||
wsWebSocketContainer.defaultConfiguratorFail=기본 Configurator를 생성하지 못했습니다.
|
||||
wsWebSocketContainer.endpointCreateFail=타입이 [{0}]인 로컬 엔드포인트를 생성하지 못했습니다.
|
||||
wsWebSocketContainer.failedAuthentication=HTTP 응답 코드 [{0}]을(를) 처리하지 못했습니다. 인증 헤더가 서버에 의해 받아들여지지 않았습니다.
|
||||
wsWebSocketContainer.httpRequestFailed=웹소켓 연결을 초기화하기 위한 HTTP 요청이 실패했습니다.
|
||||
wsWebSocketContainer.invalidExtensionParameters=서버가, 클라이언트가 지원할 수 없는 확장 파라미터들과 함께 응답했습니다.
|
||||
wsWebSocketContainer.invalidHeader=[{0}] 내에서, 헤더 이름과 헤더 값을 구분하기 위한 콜론('':'')이 존재하지 않기에, HTTP 헤더를 파싱할 수 없습니다. 해당 헤더를 건너뛰었습니다.
|
||||
wsWebSocketContainer.invalidStatus=서버 [{0}](으)로부터의 HTTP 응답은, 웹소켓으로 HTTP 업그레이드를 허용하지 않았습니다.
|
||||
wsWebSocketContainer.invalidSubProtocol=웹소켓 서버가, 해당 Sec-WebSocket-Protocol 헤더를 위해 여러 값들을 반환했습니다.
|
||||
wsWebSocketContainer.maxBuffer=이 구현은 버퍼의 최대 크기를 Integer.MAX_VALUE로 제한합니다.
|
||||
wsWebSocketContainer.missingAnnotation=@ClientEndpoint에 의해 annotate되지 않았기에, POJO 클래스 [{0}]을(를) 사용할 수 없습니다.
|
||||
wsWebSocketContainer.missingLocationHeader=HTTP 응답 코드 [{0}]을(를) 처리하지 못했습니다. 응답에 Location 헤더가 없습니다.
|
||||
wsWebSocketContainer.missingWWWAuthenticateHeader=HTTP 응답 코드 [{0}]을(를) 처리하지 못했습니다. 응답 헤더 WWW-Authenticate가 없습니다.
|
||||
wsWebSocketContainer.pathNoHost=URI 내에 호스트가 지정되지 않았습니다.
|
||||
wsWebSocketContainer.pathWrongScheme=스킴 [{0}]은(는) 지원되지 않습니다. 지원되는 스킴들은 ws와 wss입니다.
|
||||
wsWebSocketContainer.proxyConnectFail=설정된 프록시 [{0}](으)로 연결하지 못했습니다. HTTP 응답 코드는 [{1}]이었습니다.
|
||||
wsWebSocketContainer.redirectThreshold=순환 Location 헤더 [{0}]이(가) 탐지되었고, 최대 redirect 회수에 도달했습니다. 최대 [{2}]회 중 [{1}]회.
|
||||
wsWebSocketContainer.sessionCloseFail=ID가 [{0}]인 세션이 깨끗하게 닫히지 않았습니다.
|
||||
wsWebSocketContainer.shutdown=웹 애플리케이션이 중지되고 있습니다.
|
||||
wsWebSocketContainer.sslEngineFail=SSL/TLS 연결들을 지원하는 SSLEngine을 생성할 수 없습니다.
|
||||
wsWebSocketContainer.unsupportedAuthScheme=HTTP 응답 코드 [{0}]을(를) 처리하지 못했습니다. 지원되지 않는 인증 스킴 [{1}]이(가) 응답에서 반환되었습니다.
|
||||
20
java/org/apache/tomcat/websocket/LocalStrings_ru.properties
Normal file
20
java/org/apache/tomcat/websocket/LocalStrings_ru.properties
Normal file
@@ -0,0 +1,20 @@
|
||||
# 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.
|
||||
|
||||
caseInsensitiveKeyMap.nullKey=Пустое значение ключей запрещено
|
||||
|
||||
wsHandshakeRequest.invalidUri=Строка [{0}] не может быть использована для создания корректного URI
|
||||
|
||||
wsSession.doClose=Закрытие WebSocket сессии [{1}]
|
||||
@@ -0,0 +1,78 @@
|
||||
# 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.
|
||||
|
||||
asyncChannelGroup.createFail=无法为WebSocket客户端创建专用的异步通道组,这是防止复杂类加载程序环境(如JavaEE容器)中内存泄漏所必需的
|
||||
|
||||
asyncChannelWrapperSecure.check.notOk=TLS握手返回意外状态[{0}]
|
||||
asyncChannelWrapperSecure.check.unwrap=在读取期间将字节写入输出
|
||||
asyncChannelWrapperSecure.closeFail=干净的关闭通道失败
|
||||
asyncChannelWrapperSecure.eof=意外的流结尾
|
||||
asyncChannelWrapperSecure.statusUnwrap=unwrap()操作后SSLEngineResult 的意外状态
|
||||
|
||||
backgroundProcessManager.processFailed=后台进程失败
|
||||
|
||||
caseInsensitiveKeyMap.nullKey=不允许 Key 是 Null
|
||||
|
||||
perMessageDeflate.deflateFailed=无法压缩这个WebSocket压缩结构
|
||||
perMessageDeflate.duplicateParameter=重复定义的扩展参数[{0}]
|
||||
perMessageDeflate.invalidWindowSize=为[{0}]指定了[{1}]大小的无效窗口。 有效值是从8到15(包括8和15)的整数。
|
||||
|
||||
util.notToken=一个非法的扩展参数被指定为名称[{0}]和值[{0}]
|
||||
util.unknownDecoderType=无法识别该解码器类型[{0}]
|
||||
|
||||
wsFrame.alreadySuspended=消息接收已挂起。
|
||||
wsFrame.byteToLongFail=提供了太多字节([{0}]),转换成一个长的字节。
|
||||
wsFrame.closed=在一个关闭的控制帧后受到了一个新的帧.
|
||||
wsFrame.controlFragmented=接收到分段的控制帧,但控制帧可能不被分割。
|
||||
wsFrame.controlNoFin=发送一个没有设置的控制帧。控制帧不允许使用连续帧。
|
||||
wsFrame.controlPayloadTooBig=以大于125字节的最大允许值的大小[{0}]的有效载荷发送控制帧。
|
||||
wsFrame.illegalReadState=意外的读状态[{0}]
|
||||
wsFrame.invalidUtf8Close=接收到一个WebSocket关闭帧,其关闭原因包含无效的UTF-8字节序列
|
||||
wsFrame.notMasked=客户端帧未被屏蔽,但必须屏蔽所有客户端帧
|
||||
wsFrame.partialHeaderComplete=接收到WebSocket帧. fin [{0}], rsv [{1}], OpCode [{2}], payload 长度 [{3}]
|
||||
wsFrame.sessionClosed=无法处理客户端数据,因为会话已被关闭
|
||||
wsFrame.textMessageTooBig=解码的文本消息对于输出缓冲区太大,终结点不支持部分消息
|
||||
wsFrame.wrongRsv=对于具有opCode [{1}]的消息,客户端帧将保留位设置为[{0}],此端点不支持
|
||||
|
||||
wsHandshakeRequest.invalidUri=字符串 [{0}] 不能用来组成一个有效的URI
|
||||
|
||||
wsRemoteEndpoint.acquireTimeout=当前消息没有在指定的超时内完全发送
|
||||
wsRemoteEndpoint.changeType=发送分段消息时,所有片段必须是相同类型的。
|
||||
wsRemoteEndpoint.closed=由于 WebSocket session 已关闭,消息将不会被发送
|
||||
wsRemoteEndpoint.closedDuringMessage=因为 WebSocket session 被关闭,消息的剩余部分将不会被送达
|
||||
wsRemoteEndpoint.flushOnCloseFailed=会话关闭后仍然启用批处理消息。无法刷新剩余的批量消息
|
||||
wsRemoteEndpoint.noEncoder=没有为类 [{0}] 的对象指定编码器
|
||||
wsRemoteEndpoint.nullData=无效空的data 参数
|
||||
wsRemoteEndpoint.sendInterrupt=当前线程在等待阻塞发送完成时被中断
|
||||
wsRemoteEndpoint.tooMuchData=ping或pong不应该发送超过125字节
|
||||
wsRemoteEndpoint.wrongState=远程 endpoint 处于 [{0}] 状态,是被调用方法的无效状态
|
||||
|
||||
wsSession.closed=WebSocket会话[{0}]已关闭,并且在关闭的会话上不能调用任何方法(除了close())
|
||||
wsSession.created=创建WebSocket session [{0}]。
|
||||
wsSession.doClose=关闭 WebSocket session [{1}]
|
||||
wsSession.duplicateHandlerText=已配置文本消息处理器
|
||||
wsSession.instanceNew=endpoint 实例注册失败
|
||||
wsSession.unknownHandler=无法添加消息处理程序[{0}],因为它是针对无法识别的类型[{1}]
|
||||
|
||||
wsWebSocketContainer.asynchronousSocketChannelFail=无法打开与服务器的连接
|
||||
wsWebSocketContainer.failedAuthentication=无法处理http响应代码[{0}]。服务器不接受身份验证头。
|
||||
wsWebSocketContainer.invalidExtensionParameters=服务器用客户端无法支持的扩展参数响应
|
||||
wsWebSocketContainer.missingAnnotation=无法使用POJO类[{0}],因为它未添加注解@ClientEndpoint
|
||||
wsWebSocketContainer.missingLocationHeader=处理HTTP响应码 [{0}] 失败。响应头缺少Location
|
||||
wsWebSocketContainer.missingWWWAuthenticateHeader=无法处理HTTP响应代码[{0}]。 缺少WWW-Authenticate标头作为响应
|
||||
wsWebSocketContainer.pathNoHost=URI中未指定主机
|
||||
wsWebSocketContainer.sessionCloseFail=ID 为 [{0}] 的session 没有彻底关闭
|
||||
wsWebSocketContainer.shutdown=web应用程序正在停止
|
||||
wsWebSocketContainer.sslEngineFail=无法创建SSLEngine以支持SSL/TLS连接
|
||||
42
java/org/apache/tomcat/websocket/MessageHandlerResult.java
Normal file
42
java/org/apache/tomcat/websocket/MessageHandlerResult.java
Normal file
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import javax.websocket.MessageHandler;
|
||||
|
||||
public class MessageHandlerResult {
|
||||
|
||||
private final MessageHandler handler;
|
||||
private final MessageHandlerResultType type;
|
||||
|
||||
|
||||
public MessageHandlerResult(MessageHandler handler,
|
||||
MessageHandlerResultType type) {
|
||||
this.handler = handler;
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
|
||||
public MessageHandler getHandler() {
|
||||
return handler;
|
||||
}
|
||||
|
||||
|
||||
public MessageHandlerResultType getType() {
|
||||
return type;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
public enum MessageHandlerResultType {
|
||||
BINARY,
|
||||
TEXT,
|
||||
PONG
|
||||
}
|
||||
83
java/org/apache/tomcat/websocket/MessagePart.java
Normal file
83
java/org/apache/tomcat/websocket/MessagePart.java
Normal file
@@ -0,0 +1,83 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import javax.websocket.SendHandler;
|
||||
|
||||
class MessagePart {
|
||||
private final boolean fin;
|
||||
private final int rsv;
|
||||
private final byte opCode;
|
||||
private final ByteBuffer payload;
|
||||
private final SendHandler intermediateHandler;
|
||||
private volatile SendHandler endHandler;
|
||||
private final long blockingWriteTimeoutExpiry;
|
||||
|
||||
public MessagePart( boolean fin, int rsv, byte opCode, ByteBuffer payload,
|
||||
SendHandler intermediateHandler, SendHandler endHandler,
|
||||
long blockingWriteTimeoutExpiry) {
|
||||
this.fin = fin;
|
||||
this.rsv = rsv;
|
||||
this.opCode = opCode;
|
||||
this.payload = payload;
|
||||
this.intermediateHandler = intermediateHandler;
|
||||
this.endHandler = endHandler;
|
||||
this.blockingWriteTimeoutExpiry = blockingWriteTimeoutExpiry;
|
||||
}
|
||||
|
||||
|
||||
public boolean isFin() {
|
||||
return fin;
|
||||
}
|
||||
|
||||
|
||||
public int getRsv() {
|
||||
return rsv;
|
||||
}
|
||||
|
||||
|
||||
public byte getOpCode() {
|
||||
return opCode;
|
||||
}
|
||||
|
||||
|
||||
public ByteBuffer getPayload() {
|
||||
return payload;
|
||||
}
|
||||
|
||||
|
||||
public SendHandler getIntermediateHandler() {
|
||||
return intermediateHandler;
|
||||
}
|
||||
|
||||
|
||||
public SendHandler getEndHandler() {
|
||||
return endHandler;
|
||||
}
|
||||
|
||||
public void setEndHandler(SendHandler endHandler) {
|
||||
this.endHandler = endHandler;
|
||||
}
|
||||
|
||||
public long getBlockingWriteTimeoutExpiry() {
|
||||
return blockingWriteTimeoutExpiry;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
495
java/org/apache/tomcat/websocket/PerMessageDeflate.java
Normal file
495
java/org/apache/tomcat/websocket/PerMessageDeflate.java
Normal file
@@ -0,0 +1,495 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.zip.DataFormatException;
|
||||
import java.util.zip.Deflater;
|
||||
import java.util.zip.Inflater;
|
||||
|
||||
import javax.websocket.Extension;
|
||||
import javax.websocket.Extension.Parameter;
|
||||
import javax.websocket.SendHandler;
|
||||
|
||||
import org.apache.tomcat.util.res.StringManager;
|
||||
|
||||
public class PerMessageDeflate implements Transformation {
|
||||
|
||||
private static final StringManager sm = StringManager.getManager(PerMessageDeflate.class);
|
||||
|
||||
private static final String SERVER_NO_CONTEXT_TAKEOVER = "server_no_context_takeover";
|
||||
private static final String CLIENT_NO_CONTEXT_TAKEOVER = "client_no_context_takeover";
|
||||
private static final String SERVER_MAX_WINDOW_BITS = "server_max_window_bits";
|
||||
private static final String CLIENT_MAX_WINDOW_BITS = "client_max_window_bits";
|
||||
|
||||
private static final int RSV_BITMASK = 0b100;
|
||||
private static final byte[] EOM_BYTES = new byte[] {0, 0, -1, -1};
|
||||
|
||||
public static final String NAME = "permessage-deflate";
|
||||
|
||||
private final boolean serverContextTakeover;
|
||||
private final int serverMaxWindowBits;
|
||||
private final boolean clientContextTakeover;
|
||||
private final int clientMaxWindowBits;
|
||||
private final boolean isServer;
|
||||
private final Inflater inflater = new Inflater(true);
|
||||
private final ByteBuffer readBuffer = ByteBuffer.allocate(Constants.DEFAULT_BUFFER_SIZE);
|
||||
private final Deflater deflater = new Deflater(Deflater.DEFAULT_COMPRESSION, true);
|
||||
private final byte[] EOM_BUFFER = new byte[EOM_BYTES.length + 1];
|
||||
|
||||
private volatile Transformation next;
|
||||
private volatile boolean skipDecompression = false;
|
||||
private volatile ByteBuffer writeBuffer = ByteBuffer.allocate(Constants.DEFAULT_BUFFER_SIZE);
|
||||
private volatile boolean firstCompressedFrameWritten = false;
|
||||
// Flag to track if a message is completely empty
|
||||
private volatile boolean emptyMessage = true;
|
||||
|
||||
static PerMessageDeflate negotiate(List<List<Parameter>> preferences, boolean isServer) {
|
||||
// Accept the first preference that the endpoint is able to support
|
||||
for (List<Parameter> preference : preferences) {
|
||||
boolean ok = true;
|
||||
boolean serverContextTakeover = true;
|
||||
int serverMaxWindowBits = -1;
|
||||
boolean clientContextTakeover = true;
|
||||
int clientMaxWindowBits = -1;
|
||||
|
||||
for (Parameter param : preference) {
|
||||
if (SERVER_NO_CONTEXT_TAKEOVER.equals(param.getName())) {
|
||||
if (serverContextTakeover) {
|
||||
serverContextTakeover = false;
|
||||
} else {
|
||||
// Duplicate definition
|
||||
throw new IllegalArgumentException(sm.getString(
|
||||
"perMessageDeflate.duplicateParameter",
|
||||
SERVER_NO_CONTEXT_TAKEOVER ));
|
||||
}
|
||||
} else if (CLIENT_NO_CONTEXT_TAKEOVER.equals(param.getName())) {
|
||||
if (clientContextTakeover) {
|
||||
clientContextTakeover = false;
|
||||
} else {
|
||||
// Duplicate definition
|
||||
throw new IllegalArgumentException(sm.getString(
|
||||
"perMessageDeflate.duplicateParameter",
|
||||
CLIENT_NO_CONTEXT_TAKEOVER ));
|
||||
}
|
||||
} else if (SERVER_MAX_WINDOW_BITS.equals(param.getName())) {
|
||||
if (serverMaxWindowBits == -1) {
|
||||
serverMaxWindowBits = Integer.parseInt(param.getValue());
|
||||
if (serverMaxWindowBits < 8 || serverMaxWindowBits > 15) {
|
||||
throw new IllegalArgumentException(sm.getString(
|
||||
"perMessageDeflate.invalidWindowSize",
|
||||
SERVER_MAX_WINDOW_BITS,
|
||||
Integer.valueOf(serverMaxWindowBits)));
|
||||
}
|
||||
// Java SE API (as of Java 8) does not expose the API to
|
||||
// control the Window size. It is effectively hard-coded
|
||||
// to 15
|
||||
if (isServer && serverMaxWindowBits != 15) {
|
||||
ok = false;
|
||||
break;
|
||||
// Note server window size is not an issue for the
|
||||
// client since the client will assume 15 and if the
|
||||
// server uses a smaller window everything will
|
||||
// still work
|
||||
}
|
||||
} else {
|
||||
// Duplicate definition
|
||||
throw new IllegalArgumentException(sm.getString(
|
||||
"perMessageDeflate.duplicateParameter",
|
||||
SERVER_MAX_WINDOW_BITS ));
|
||||
}
|
||||
} else if (CLIENT_MAX_WINDOW_BITS.equals(param.getName())) {
|
||||
if (clientMaxWindowBits == -1) {
|
||||
if (param.getValue() == null) {
|
||||
// Hint to server that the client supports this
|
||||
// option. Java SE API (as of Java 8) does not
|
||||
// expose the API to control the Window size. It is
|
||||
// effectively hard-coded to 15
|
||||
clientMaxWindowBits = 15;
|
||||
} else {
|
||||
clientMaxWindowBits = Integer.parseInt(param.getValue());
|
||||
if (clientMaxWindowBits < 8 || clientMaxWindowBits > 15) {
|
||||
throw new IllegalArgumentException(sm.getString(
|
||||
"perMessageDeflate.invalidWindowSize",
|
||||
CLIENT_MAX_WINDOW_BITS,
|
||||
Integer.valueOf(clientMaxWindowBits)));
|
||||
}
|
||||
}
|
||||
// Java SE API (as of Java 8) does not expose the API to
|
||||
// control the Window size. It is effectively hard-coded
|
||||
// to 15
|
||||
if (!isServer && clientMaxWindowBits != 15) {
|
||||
ok = false;
|
||||
break;
|
||||
// Note client window size is not an issue for the
|
||||
// server since the server will assume 15 and if the
|
||||
// client uses a smaller window everything will
|
||||
// still work
|
||||
}
|
||||
} else {
|
||||
// Duplicate definition
|
||||
throw new IllegalArgumentException(sm.getString(
|
||||
"perMessageDeflate.duplicateParameter",
|
||||
CLIENT_MAX_WINDOW_BITS ));
|
||||
}
|
||||
} else {
|
||||
// Unknown parameter
|
||||
throw new IllegalArgumentException(sm.getString(
|
||||
"perMessageDeflate.unknownParameter", param.getName()));
|
||||
}
|
||||
}
|
||||
if (ok) {
|
||||
return new PerMessageDeflate(serverContextTakeover, serverMaxWindowBits,
|
||||
clientContextTakeover, clientMaxWindowBits, isServer);
|
||||
}
|
||||
}
|
||||
// Failed to negotiate agreeable terms
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
private PerMessageDeflate(boolean serverContextTakeover, int serverMaxWindowBits,
|
||||
boolean clientContextTakeover, int clientMaxWindowBits, boolean isServer) {
|
||||
this.serverContextTakeover = serverContextTakeover;
|
||||
this.serverMaxWindowBits = serverMaxWindowBits;
|
||||
this.clientContextTakeover = clientContextTakeover;
|
||||
this.clientMaxWindowBits = clientMaxWindowBits;
|
||||
this.isServer = isServer;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public TransformationResult getMoreData(byte opCode, boolean fin, int rsv, ByteBuffer dest)
|
||||
throws IOException {
|
||||
// Control frames are never compressed and may appear in the middle of
|
||||
// a WebSocket method. Pass them straight through.
|
||||
if (Util.isControl(opCode)) {
|
||||
return next.getMoreData(opCode, fin, rsv, dest);
|
||||
}
|
||||
|
||||
if (!Util.isContinuation(opCode)) {
|
||||
// First frame in new message
|
||||
skipDecompression = (rsv & RSV_BITMASK) == 0;
|
||||
}
|
||||
|
||||
// Pass uncompressed frames straight through.
|
||||
if (skipDecompression) {
|
||||
return next.getMoreData(opCode, fin, rsv, dest);
|
||||
}
|
||||
|
||||
int written;
|
||||
boolean usedEomBytes = false;
|
||||
|
||||
while (dest.remaining() > 0) {
|
||||
// Space available in destination. Try and fill it.
|
||||
try {
|
||||
written = inflater.inflate(
|
||||
dest.array(), dest.arrayOffset() + dest.position(), dest.remaining());
|
||||
} catch (DataFormatException e) {
|
||||
throw new IOException(sm.getString("perMessageDeflate.deflateFailed"), e);
|
||||
} catch (NullPointerException e) {
|
||||
throw new IOException(sm.getString("perMessageDeflate.alreadyClosed"), e);
|
||||
}
|
||||
dest.position(dest.position() + written);
|
||||
|
||||
if (inflater.needsInput() && !usedEomBytes ) {
|
||||
if (dest.hasRemaining()) {
|
||||
readBuffer.clear();
|
||||
TransformationResult nextResult =
|
||||
next.getMoreData(opCode, fin, (rsv ^ RSV_BITMASK), readBuffer);
|
||||
inflater.setInput(
|
||||
readBuffer.array(), readBuffer.arrayOffset(), readBuffer.position());
|
||||
if (TransformationResult.UNDERFLOW.equals(nextResult)) {
|
||||
return nextResult;
|
||||
} else if (TransformationResult.END_OF_FRAME.equals(nextResult) &&
|
||||
readBuffer.position() == 0) {
|
||||
if (fin) {
|
||||
inflater.setInput(EOM_BYTES);
|
||||
usedEomBytes = true;
|
||||
} else {
|
||||
return TransformationResult.END_OF_FRAME;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (written == 0) {
|
||||
if (fin && (isServer && !clientContextTakeover ||
|
||||
!isServer && !serverContextTakeover)) {
|
||||
try {
|
||||
inflater.reset();
|
||||
} catch (NullPointerException e) {
|
||||
throw new IOException(sm.getString("perMessageDeflate.alreadyClosed"), e);
|
||||
}
|
||||
}
|
||||
return TransformationResult.END_OF_FRAME;
|
||||
}
|
||||
}
|
||||
|
||||
return TransformationResult.OVERFLOW;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean validateRsv(int rsv, byte opCode) {
|
||||
if (Util.isControl(opCode)) {
|
||||
if ((rsv & RSV_BITMASK) != 0) {
|
||||
return false;
|
||||
} else {
|
||||
if (next == null) {
|
||||
return true;
|
||||
} else {
|
||||
return next.validateRsv(rsv, opCode);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
int rsvNext = rsv;
|
||||
if ((rsv & RSV_BITMASK) != 0) {
|
||||
rsvNext = rsv ^ RSV_BITMASK;
|
||||
}
|
||||
if (next == null) {
|
||||
return true;
|
||||
} else {
|
||||
return next.validateRsv(rsvNext, opCode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Extension getExtensionResponse() {
|
||||
Extension result = new WsExtension(NAME);
|
||||
|
||||
List<Extension.Parameter> params = result.getParameters();
|
||||
|
||||
if (!serverContextTakeover) {
|
||||
params.add(new WsExtensionParameter(SERVER_NO_CONTEXT_TAKEOVER, null));
|
||||
}
|
||||
if (serverMaxWindowBits != -1) {
|
||||
params.add(new WsExtensionParameter(SERVER_MAX_WINDOW_BITS,
|
||||
Integer.toString(serverMaxWindowBits)));
|
||||
}
|
||||
if (!clientContextTakeover) {
|
||||
params.add(new WsExtensionParameter(CLIENT_NO_CONTEXT_TAKEOVER, null));
|
||||
}
|
||||
if (clientMaxWindowBits != -1) {
|
||||
params.add(new WsExtensionParameter(CLIENT_MAX_WINDOW_BITS,
|
||||
Integer.toString(clientMaxWindowBits)));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void setNext(Transformation t) {
|
||||
if (next == null) {
|
||||
this.next = t;
|
||||
} else {
|
||||
next.setNext(t);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean validateRsvBits(int i) {
|
||||
if ((i & RSV_BITMASK) != 0) {
|
||||
return false;
|
||||
}
|
||||
if (next == null) {
|
||||
return true;
|
||||
} else {
|
||||
return next.validateRsvBits(i | RSV_BITMASK);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public List<MessagePart> sendMessagePart(List<MessagePart> uncompressedParts) throws IOException {
|
||||
List<MessagePart> allCompressedParts = new ArrayList<>();
|
||||
|
||||
for (MessagePart uncompressedPart : uncompressedParts) {
|
||||
byte opCode = uncompressedPart.getOpCode();
|
||||
boolean emptyPart = uncompressedPart.getPayload().limit() == 0;
|
||||
emptyMessage = emptyMessage && emptyPart;
|
||||
if (Util.isControl(opCode)) {
|
||||
// Control messages can appear in the middle of other messages
|
||||
// and must not be compressed. Pass it straight through
|
||||
allCompressedParts.add(uncompressedPart);
|
||||
} else if (emptyMessage && uncompressedPart.isFin()) {
|
||||
// Zero length messages can't be compressed so pass the
|
||||
// final (empty) part straight through.
|
||||
allCompressedParts.add(uncompressedPart);
|
||||
} else {
|
||||
List<MessagePart> compressedParts = new ArrayList<>();
|
||||
ByteBuffer uncompressedPayload = uncompressedPart.getPayload();
|
||||
SendHandler uncompressedIntermediateHandler =
|
||||
uncompressedPart.getIntermediateHandler();
|
||||
|
||||
deflater.setInput(uncompressedPayload.array(),
|
||||
uncompressedPayload.arrayOffset() + uncompressedPayload.position(),
|
||||
uncompressedPayload.remaining());
|
||||
|
||||
int flush = (uncompressedPart.isFin() ? Deflater.SYNC_FLUSH : Deflater.NO_FLUSH);
|
||||
boolean deflateRequired = true;
|
||||
|
||||
while (deflateRequired) {
|
||||
ByteBuffer compressedPayload = writeBuffer;
|
||||
|
||||
try {
|
||||
int written = deflater.deflate(compressedPayload.array(),
|
||||
compressedPayload.arrayOffset() + compressedPayload.position(),
|
||||
compressedPayload.remaining(), flush);
|
||||
compressedPayload.position(compressedPayload.position() + written);
|
||||
} catch (NullPointerException e) {
|
||||
throw new IOException(sm.getString("perMessageDeflate.alreadyClosed"), e);
|
||||
}
|
||||
|
||||
if (!uncompressedPart.isFin() && compressedPayload.hasRemaining() && deflater.needsInput()) {
|
||||
// This message part has been fully processed by the
|
||||
// deflater. Fire the send handler for this message part
|
||||
// and move on to the next message part.
|
||||
break;
|
||||
}
|
||||
|
||||
// If this point is reached, a new compressed message part
|
||||
// will be created...
|
||||
MessagePart compressedPart;
|
||||
|
||||
// .. and a new writeBuffer will be required.
|
||||
writeBuffer = ByteBuffer.allocate(Constants.DEFAULT_BUFFER_SIZE);
|
||||
|
||||
// Flip the compressed payload ready for writing
|
||||
compressedPayload.flip();
|
||||
|
||||
boolean fin = uncompressedPart.isFin();
|
||||
boolean full = compressedPayload.limit() == compressedPayload.capacity();
|
||||
boolean needsInput = deflater.needsInput();
|
||||
long blockingWriteTimeoutExpiry = uncompressedPart.getBlockingWriteTimeoutExpiry();
|
||||
|
||||
if (fin && !full && needsInput) {
|
||||
// End of compressed message. Drop EOM bytes and output.
|
||||
compressedPayload.limit(compressedPayload.limit() - EOM_BYTES.length);
|
||||
compressedPart = new MessagePart(true, getRsv(uncompressedPart),
|
||||
opCode, compressedPayload, uncompressedIntermediateHandler,
|
||||
uncompressedIntermediateHandler, blockingWriteTimeoutExpiry);
|
||||
deflateRequired = false;
|
||||
startNewMessage();
|
||||
} else if (full && !needsInput) {
|
||||
// Write buffer full and input message not fully read.
|
||||
// Output and start new compressed part.
|
||||
compressedPart = new MessagePart(false, getRsv(uncompressedPart),
|
||||
opCode, compressedPayload, uncompressedIntermediateHandler,
|
||||
uncompressedIntermediateHandler, blockingWriteTimeoutExpiry);
|
||||
} else if (!fin && full && needsInput) {
|
||||
// Write buffer full and input message not fully read.
|
||||
// Output and get more data.
|
||||
compressedPart = new MessagePart(false, getRsv(uncompressedPart),
|
||||
opCode, compressedPayload, uncompressedIntermediateHandler,
|
||||
uncompressedIntermediateHandler, blockingWriteTimeoutExpiry);
|
||||
deflateRequired = false;
|
||||
} else if (fin && full && needsInput) {
|
||||
// Write buffer full. Input fully read. Deflater may be
|
||||
// in one of four states:
|
||||
// - output complete (just happened to align with end of
|
||||
// buffer
|
||||
// - in middle of EOM bytes
|
||||
// - about to write EOM bytes
|
||||
// - more data to write
|
||||
int eomBufferWritten;
|
||||
try {
|
||||
eomBufferWritten = deflater.deflate(EOM_BUFFER, 0, EOM_BUFFER.length, Deflater.SYNC_FLUSH);
|
||||
} catch (NullPointerException e) {
|
||||
throw new IOException(sm.getString("perMessageDeflate.alreadyClosed"), e);
|
||||
}
|
||||
if (eomBufferWritten < EOM_BUFFER.length) {
|
||||
// EOM has just been completed
|
||||
compressedPayload.limit(compressedPayload.limit() - EOM_BYTES.length + eomBufferWritten);
|
||||
compressedPart = new MessagePart(true,
|
||||
getRsv(uncompressedPart), opCode, compressedPayload,
|
||||
uncompressedIntermediateHandler, uncompressedIntermediateHandler,
|
||||
blockingWriteTimeoutExpiry);
|
||||
deflateRequired = false;
|
||||
startNewMessage();
|
||||
} else {
|
||||
// More data to write
|
||||
// Copy bytes to new write buffer
|
||||
writeBuffer.put(EOM_BUFFER, 0, eomBufferWritten);
|
||||
compressedPart = new MessagePart(false,
|
||||
getRsv(uncompressedPart), opCode, compressedPayload,
|
||||
uncompressedIntermediateHandler, uncompressedIntermediateHandler,
|
||||
blockingWriteTimeoutExpiry);
|
||||
}
|
||||
} else {
|
||||
throw new IllegalStateException(sm.getString("perMessageDeflate.invalidState"));
|
||||
}
|
||||
|
||||
// Add the newly created compressed part to the set of parts
|
||||
// to pass on to the next transformation.
|
||||
compressedParts.add(compressedPart);
|
||||
}
|
||||
|
||||
SendHandler uncompressedEndHandler = uncompressedPart.getEndHandler();
|
||||
int size = compressedParts.size();
|
||||
if (size > 0) {
|
||||
compressedParts.get(size - 1).setEndHandler(uncompressedEndHandler);
|
||||
}
|
||||
|
||||
allCompressedParts.addAll(compressedParts);
|
||||
}
|
||||
}
|
||||
|
||||
if (next == null) {
|
||||
return allCompressedParts;
|
||||
} else {
|
||||
return next.sendMessagePart(allCompressedParts);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void startNewMessage() throws IOException {
|
||||
firstCompressedFrameWritten = false;
|
||||
emptyMessage = true;
|
||||
if (isServer && !serverContextTakeover || !isServer && !clientContextTakeover) {
|
||||
try {
|
||||
deflater.reset();
|
||||
} catch (NullPointerException e) {
|
||||
throw new IOException(sm.getString("perMessageDeflate.alreadyClosed"), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private int getRsv(MessagePart uncompressedMessagePart) {
|
||||
int result = uncompressedMessagePart.getRsv();
|
||||
if (!firstCompressedFrameWritten) {
|
||||
result += RSV_BITMASK;
|
||||
firstCompressedFrameWritten = true;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
// There will always be a next transformation
|
||||
next.close();
|
||||
inflater.end();
|
||||
deflater.end();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public class ReadBufferOverflowException extends IOException {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private final int minBufferSize;
|
||||
|
||||
public ReadBufferOverflowException(int minBufferSize) {
|
||||
this.minBufferSize = minBufferSize;
|
||||
}
|
||||
|
||||
public int getMinBufferSize() {
|
||||
return minBufferSize;
|
||||
}
|
||||
}
|
||||
114
java/org/apache/tomcat/websocket/Transformation.java
Normal file
114
java/org/apache/tomcat/websocket/Transformation.java
Normal file
@@ -0,0 +1,114 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.List;
|
||||
|
||||
import javax.websocket.Extension;
|
||||
|
||||
/**
|
||||
* The internal representation of the transformation that a WebSocket extension
|
||||
* performs on a message.
|
||||
*/
|
||||
public interface Transformation {
|
||||
|
||||
/**
|
||||
* Sets the next transformation in the pipeline.
|
||||
* @param t The next transformation
|
||||
*/
|
||||
void setNext(Transformation t);
|
||||
|
||||
/**
|
||||
* Validate that the RSV bit(s) required by this transformation are not
|
||||
* being used by another extension. The implementation is expected to set
|
||||
* any bits it requires before passing the set of in-use bits to the next
|
||||
* transformation.
|
||||
*
|
||||
* @param i The RSV bits marked as in use so far as an int in the
|
||||
* range zero to seven with RSV1 as the MSB and RSV3 as the
|
||||
* LSB
|
||||
*
|
||||
* @return <code>true</code> if the combination of RSV bits used by the
|
||||
* transformations in the pipeline do not conflict otherwise
|
||||
* <code>false</code>
|
||||
*/
|
||||
boolean validateRsvBits(int i);
|
||||
|
||||
/**
|
||||
* Obtain the extension that describes the information to be returned to the
|
||||
* client.
|
||||
*
|
||||
* @return The extension information that describes the parameters that have
|
||||
* been agreed for this transformation
|
||||
*/
|
||||
Extension getExtensionResponse();
|
||||
|
||||
/**
|
||||
* Obtain more input data.
|
||||
*
|
||||
* @param opCode The opcode for the frame currently being processed
|
||||
* @param fin Is this the final frame in this WebSocket message?
|
||||
* @param rsv The reserved bits for the frame currently being
|
||||
* processed
|
||||
* @param dest The buffer in which the data is to be written
|
||||
*
|
||||
* @return The result of trying to read more data from the transform
|
||||
*
|
||||
* @throws IOException If an I/O error occurs while reading data from the
|
||||
* transform
|
||||
*/
|
||||
TransformationResult getMoreData(byte opCode, boolean fin, int rsv, ByteBuffer dest) throws IOException;
|
||||
|
||||
/**
|
||||
* Validates the RSV and opcode combination (assumed to have been extracted
|
||||
* from a WebSocket Frame) for this extension. The implementation is
|
||||
* expected to unset any RSV bits it has validated before passing the
|
||||
* remaining RSV bits to the next transformation in the pipeline.
|
||||
*
|
||||
* @param rsv The RSV bits received as an int in the range zero to
|
||||
* seven with RSV1 as the MSB and RSV3 as the LSB
|
||||
* @param opCode The opCode received
|
||||
*
|
||||
* @return <code>true</code> if the RSV is valid otherwise
|
||||
* <code>false</code>
|
||||
*/
|
||||
boolean validateRsv(int rsv, byte opCode);
|
||||
|
||||
/**
|
||||
* Takes the provided list of messages, transforms them, passes the
|
||||
* transformed list on to the next transformation (if any) and then returns
|
||||
* the resulting list of message parts after all of the transformations have
|
||||
* been applied.
|
||||
*
|
||||
* @param messageParts The list of messages to be transformed
|
||||
*
|
||||
* @return The list of messages after this any any subsequent
|
||||
* transformations have been applied. The size of the returned list
|
||||
* may be bigger or smaller than the size of the input list
|
||||
*
|
||||
* @throws IOException If an error occurs during the transformation of the
|
||||
* message parts
|
||||
*/
|
||||
List<MessagePart> sendMessagePart(List<MessagePart> messageParts) throws IOException;
|
||||
|
||||
/**
|
||||
* Clean-up any resources that were used by the transformation.
|
||||
*/
|
||||
void close();
|
||||
}
|
||||
51
java/org/apache/tomcat/websocket/TransformationFactory.java
Normal file
51
java/org/apache/tomcat/websocket/TransformationFactory.java
Normal file
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import javax.websocket.Extension;
|
||||
|
||||
import org.apache.tomcat.util.res.StringManager;
|
||||
|
||||
public class TransformationFactory {
|
||||
|
||||
private static final StringManager sm = StringManager.getManager(TransformationFactory.class);
|
||||
|
||||
private static final TransformationFactory factory = new TransformationFactory();
|
||||
|
||||
private TransformationFactory() {
|
||||
// Hide default constructor
|
||||
}
|
||||
|
||||
public static TransformationFactory getInstance() {
|
||||
return factory;
|
||||
}
|
||||
|
||||
public Transformation create(String name, List<List<Extension.Parameter>> preferences,
|
||||
boolean isServer) {
|
||||
if (PerMessageDeflate.NAME.equals(name)) {
|
||||
return PerMessageDeflate.negotiate(preferences, isServer);
|
||||
}
|
||||
if (Constants.ALLOW_UNSUPPORTED_EXTENSIONS) {
|
||||
return null;
|
||||
} else {
|
||||
throw new IllegalArgumentException(
|
||||
sm.getString("transformerFactory.unsupportedExtension", name));
|
||||
}
|
||||
}
|
||||
}
|
||||
37
java/org/apache/tomcat/websocket/TransformationResult.java
Normal file
37
java/org/apache/tomcat/websocket/TransformationResult.java
Normal file
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
public enum TransformationResult {
|
||||
/**
|
||||
* The end of the available data was reached before the WebSocket frame was
|
||||
* completely read.
|
||||
*/
|
||||
UNDERFLOW,
|
||||
|
||||
/**
|
||||
* The provided destination buffer was filled before all of the available
|
||||
* data from the WebSocket frame could be processed.
|
||||
*/
|
||||
OVERFLOW,
|
||||
|
||||
/**
|
||||
* The end of the WebSocket frame was reached and all the data from that
|
||||
* frame processed into the provided destination buffer.
|
||||
*/
|
||||
END_OF_FRAME
|
||||
}
|
||||
666
java/org/apache/tomcat/websocket/Util.java
Normal file
666
java/org/apache/tomcat/websocket/Util.java
Normal file
File diff suppressed because it is too large
Load Diff
25
java/org/apache/tomcat/websocket/WrappedMessageHandler.java
Normal file
25
java/org/apache/tomcat/websocket/WrappedMessageHandler.java
Normal file
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import javax.websocket.MessageHandler;
|
||||
|
||||
public interface WrappedMessageHandler {
|
||||
long getMaxMessageSize();
|
||||
|
||||
MessageHandler getWrappedHandler();
|
||||
}
|
||||
28
java/org/apache/tomcat/websocket/WsContainerProvider.java
Normal file
28
java/org/apache/tomcat/websocket/WsContainerProvider.java
Normal file
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import javax.websocket.ContainerProvider;
|
||||
import javax.websocket.WebSocketContainer;
|
||||
|
||||
public class WsContainerProvider extends ContainerProvider {
|
||||
|
||||
@Override
|
||||
protected WebSocketContainer getContainer() {
|
||||
return new WsWebSocketContainer();
|
||||
}
|
||||
}
|
||||
46
java/org/apache/tomcat/websocket/WsExtension.java
Normal file
46
java/org/apache/tomcat/websocket/WsExtension.java
Normal file
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import javax.websocket.Extension;
|
||||
|
||||
public class WsExtension implements Extension {
|
||||
|
||||
private final String name;
|
||||
private final List<Parameter> parameters = new ArrayList<>();
|
||||
|
||||
WsExtension(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
void addParameter(Parameter parameter) {
|
||||
parameters.add(parameter);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Parameter> getParameters() {
|
||||
return parameters;
|
||||
}
|
||||
}
|
||||
40
java/org/apache/tomcat/websocket/WsExtensionParameter.java
Normal file
40
java/org/apache/tomcat/websocket/WsExtensionParameter.java
Normal file
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import javax.websocket.Extension.Parameter;
|
||||
|
||||
public class WsExtensionParameter implements Parameter {
|
||||
|
||||
private final String name;
|
||||
private final String value;
|
||||
|
||||
WsExtensionParameter(String name, String value) {
|
||||
this.name = name;
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getValue() {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
1011
java/org/apache/tomcat/websocket/WsFrameBase.java
Normal file
1011
java/org/apache/tomcat/websocket/WsFrameBase.java
Normal file
File diff suppressed because it is too large
Load Diff
228
java/org/apache/tomcat/websocket/WsFrameClient.java
Normal file
228
java/org/apache/tomcat/websocket/WsFrameClient.java
Normal file
@@ -0,0 +1,228 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import java.io.EOFException;
|
||||
import java.io.IOException;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.channels.CompletionHandler;
|
||||
|
||||
import javax.websocket.CloseReason;
|
||||
import javax.websocket.CloseReason.CloseCodes;
|
||||
|
||||
import org.apache.juli.logging.Log;
|
||||
import org.apache.juli.logging.LogFactory;
|
||||
import org.apache.tomcat.util.res.StringManager;
|
||||
|
||||
public class WsFrameClient extends WsFrameBase {
|
||||
|
||||
private final Log log = LogFactory.getLog(WsFrameClient.class); // must not be static
|
||||
private static final StringManager sm = StringManager.getManager(WsFrameClient.class);
|
||||
|
||||
private final AsyncChannelWrapper channel;
|
||||
private final CompletionHandler<Integer, Void> handler;
|
||||
// Not final as it may need to be re-sized
|
||||
private volatile ByteBuffer response;
|
||||
|
||||
public WsFrameClient(ByteBuffer response, AsyncChannelWrapper channel, WsSession wsSession,
|
||||
Transformation transformation) {
|
||||
super(wsSession, transformation);
|
||||
this.response = response;
|
||||
this.channel = channel;
|
||||
this.handler = new WsFrameClientCompletionHandler();
|
||||
}
|
||||
|
||||
|
||||
void startInputProcessing() {
|
||||
try {
|
||||
processSocketRead();
|
||||
} catch (IOException e) {
|
||||
close(e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void 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);
|
||||
|
||||
inputBuffer.limit(inputBuffer.position()).reset();
|
||||
|
||||
// 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:
|
||||
throw new IllegalStateException(
|
||||
sm.getString("wsFrameServer.illegalReadState", getReadState()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Fatal error. Usually an I/O error. Try and send notifications. Make sure
|
||||
* socket is closed.
|
||||
*/
|
||||
private final void 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
|
||||
protected boolean isMasked() {
|
||||
// Data is from the server so it is not masked
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected Log getLog() {
|
||||
return log;
|
||||
}
|
||||
|
||||
private class WsFrameClientCompletionHandler implements CompletionHandler<Integer, Void> {
|
||||
|
||||
@Override
|
||||
public void 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
|
||||
public void failed(Throwable exc, Void attachment) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
private void 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:
|
||||
throw new IllegalStateException(
|
||||
sm.getString("wsFrame.illegalReadState", getReadState()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void resumeProcessing() {
|
||||
resumeProcessing(true);
|
||||
}
|
||||
|
||||
private void 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
56
java/org/apache/tomcat/websocket/WsHandshakeResponse.java
Normal file
56
java/org/apache/tomcat/websocket/WsHandshakeResponse.java
Normal file
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import javax.websocket.HandshakeResponse;
|
||||
|
||||
import org.apache.tomcat.util.collections.CaseInsensitiveKeyMap;
|
||||
|
||||
/**
|
||||
* Represents the response to a WebSocket handshake.
|
||||
*/
|
||||
public class WsHandshakeResponse implements HandshakeResponse {
|
||||
|
||||
private final Map<String,List<String>> headers = new CaseInsensitiveKeyMap<>();
|
||||
|
||||
|
||||
public WsHandshakeResponse() {
|
||||
}
|
||||
|
||||
|
||||
public WsHandshakeResponse(Map<String,List<String>> headers) {
|
||||
for (Entry<String,List<String>> entry : headers.entrySet()) {
|
||||
if (this.headers.containsKey(entry.getKey())) {
|
||||
this.headers.get(entry.getKey()).addAll(entry.getValue());
|
||||
} else {
|
||||
List<String> values = new ArrayList<>(entry.getValue());
|
||||
this.headers.put(entry.getKey(), values);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Map<String,List<String>> getHeaders() {
|
||||
return headers;
|
||||
}
|
||||
}
|
||||
41
java/org/apache/tomcat/websocket/WsIOException.java
Normal file
41
java/org/apache/tomcat/websocket/WsIOException.java
Normal file
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.websocket.CloseReason;
|
||||
|
||||
/**
|
||||
* Allows the WebSocket implementation to throw an {@link IOException} that
|
||||
* includes a {@link CloseReason} specific to the error that can be passed back
|
||||
* to the client.
|
||||
*/
|
||||
public class WsIOException extends IOException {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private final CloseReason closeReason;
|
||||
|
||||
public WsIOException(CloseReason closeReason) {
|
||||
this.closeReason = closeReason;
|
||||
}
|
||||
|
||||
public CloseReason getCloseReason() {
|
||||
return closeReason;
|
||||
}
|
||||
}
|
||||
39
java/org/apache/tomcat/websocket/WsPongMessage.java
Normal file
39
java/org/apache/tomcat/websocket/WsPongMessage.java
Normal file
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import javax.websocket.PongMessage;
|
||||
|
||||
public class WsPongMessage implements PongMessage {
|
||||
|
||||
private final ByteBuffer applicationData;
|
||||
|
||||
|
||||
public WsPongMessage(ByteBuffer applicationData) {
|
||||
byte[] dst = new byte[applicationData.limit()];
|
||||
applicationData.get(dst);
|
||||
this.applicationData = ByteBuffer.wrap(dst);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public ByteBuffer getApplicationData() {
|
||||
return applicationData;
|
||||
}
|
||||
}
|
||||
79
java/org/apache/tomcat/websocket/WsRemoteEndpointAsync.java
Normal file
79
java/org/apache/tomcat/websocket/WsRemoteEndpointAsync.java
Normal file
@@ -0,0 +1,79 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.concurrent.Future;
|
||||
|
||||
import javax.websocket.RemoteEndpoint;
|
||||
import javax.websocket.SendHandler;
|
||||
|
||||
public class WsRemoteEndpointAsync extends WsRemoteEndpointBase
|
||||
implements RemoteEndpoint.Async {
|
||||
|
||||
WsRemoteEndpointAsync(WsRemoteEndpointImplBase base) {
|
||||
super(base);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public long getSendTimeout() {
|
||||
return base.getSendTimeout();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void setSendTimeout(long timeout) {
|
||||
base.setSendTimeout(timeout);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void sendText(String text, SendHandler completion) {
|
||||
base.sendStringByCompletion(text, completion);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Future<Void> sendText(String text) {
|
||||
return base.sendStringByFuture(text);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Future<Void> sendBinary(ByteBuffer data) {
|
||||
return base.sendBytesByFuture(data);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void sendBinary(ByteBuffer data, SendHandler completion) {
|
||||
base.sendBytesByCompletion(data, completion);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Future<Void> sendObject(Object obj) {
|
||||
return base.sendObjectByFuture(obj);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void sendObject(Object obj, SendHandler completion) {
|
||||
base.sendObjectByCompletion(obj, completion);
|
||||
}
|
||||
}
|
||||
64
java/org/apache/tomcat/websocket/WsRemoteEndpointBase.java
Normal file
64
java/org/apache/tomcat/websocket/WsRemoteEndpointBase.java
Normal file
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import javax.websocket.RemoteEndpoint;
|
||||
|
||||
public abstract class WsRemoteEndpointBase implements RemoteEndpoint {
|
||||
|
||||
protected final WsRemoteEndpointImplBase base;
|
||||
|
||||
|
||||
WsRemoteEndpointBase(WsRemoteEndpointImplBase base) {
|
||||
this.base = base;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public final void setBatchingAllowed(boolean batchingAllowed) throws IOException {
|
||||
base.setBatchingAllowed(batchingAllowed);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public final boolean getBatchingAllowed() {
|
||||
return base.getBatchingAllowed();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public final void flushBatch() throws IOException {
|
||||
base.flushBatch();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public final void sendPing(ByteBuffer applicationData) throws IOException,
|
||||
IllegalArgumentException {
|
||||
base.sendPing(applicationData);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public final void sendPong(ByteBuffer applicationData) throws IOException,
|
||||
IllegalArgumentException {
|
||||
base.sendPong(applicationData);
|
||||
}
|
||||
}
|
||||
76
java/org/apache/tomcat/websocket/WsRemoteEndpointBasic.java
Normal file
76
java/org/apache/tomcat/websocket/WsRemoteEndpointBasic.java
Normal file
@@ -0,0 +1,76 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.io.Writer;
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import javax.websocket.EncodeException;
|
||||
import javax.websocket.RemoteEndpoint;
|
||||
|
||||
public class WsRemoteEndpointBasic extends WsRemoteEndpointBase
|
||||
implements RemoteEndpoint.Basic {
|
||||
|
||||
WsRemoteEndpointBasic(WsRemoteEndpointImplBase base) {
|
||||
super(base);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void sendText(String text) throws IOException {
|
||||
base.sendString(text);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void sendBinary(ByteBuffer data) throws IOException {
|
||||
base.sendBytes(data);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void sendText(String fragment, boolean isLast) throws IOException {
|
||||
base.sendPartialString(fragment, isLast);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void sendBinary(ByteBuffer partialByte, boolean isLast)
|
||||
throws IOException {
|
||||
base.sendPartialBytes(partialByte, isLast);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public OutputStream getSendStream() throws IOException {
|
||||
return base.getSendStream();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Writer getSendWriter() throws IOException {
|
||||
return base.getSendWriter();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void sendObject(Object o) throws IOException, EncodeException {
|
||||
base.sendObject(o);
|
||||
}
|
||||
}
|
||||
1272
java/org/apache/tomcat/websocket/WsRemoteEndpointImplBase.java
Normal file
1272
java/org/apache/tomcat/websocket/WsRemoteEndpointImplBase.java
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
|
||||
import javax.websocket.SendHandler;
|
||||
import javax.websocket.SendResult;
|
||||
|
||||
public class WsRemoteEndpointImplClient extends WsRemoteEndpointImplBase {
|
||||
|
||||
private final AsyncChannelWrapper channel;
|
||||
|
||||
public WsRemoteEndpointImplClient(AsyncChannelWrapper channel) {
|
||||
this.channel = channel;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected boolean isMasked() {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void doWrite(SendHandler handler, long blockingWriteTimeoutExpiry,
|
||||
ByteBuffer... data) {
|
||||
long timeout;
|
||||
for (ByteBuffer byteBuffer : data) {
|
||||
if (blockingWriteTimeoutExpiry == -1) {
|
||||
timeout = getSendTimeout();
|
||||
if (timeout < 1) {
|
||||
timeout = Long.MAX_VALUE;
|
||||
}
|
||||
} else {
|
||||
timeout = blockingWriteTimeoutExpiry - System.currentTimeMillis();
|
||||
if (timeout < 0) {
|
||||
SendResult sr = new SendResult(new IOException(sm.getString("wsRemoteEndpoint.writeTimeout")));
|
||||
handler.onResult(sr);
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
channel.write(byteBuffer).get(timeout, TimeUnit.MILLISECONDS);
|
||||
} catch (InterruptedException | ExecutionException | TimeoutException e) {
|
||||
handler.onResult(new SendResult(e));
|
||||
return;
|
||||
}
|
||||
}
|
||||
handler.onResult(SENDRESULT_OK);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doClose() {
|
||||
channel.close();
|
||||
}
|
||||
}
|
||||
867
java/org/apache/tomcat/websocket/WsSession.java
Normal file
867
java/org/apache/tomcat/websocket/WsSession.java
Normal file
File diff suppressed because it is too large
Load Diff
1126
java/org/apache/tomcat/websocket/WsWebSocketContainer.java
Normal file
1126
java/org/apache/tomcat/websocket/WsWebSocketContainer.java
Normal file
File diff suppressed because it is too large
Load Diff
32
java/org/apache/tomcat/websocket/pojo/Constants.java
Normal file
32
java/org/apache/tomcat/websocket/pojo/Constants.java
Normal file
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* 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.pojo;
|
||||
|
||||
/**
|
||||
* Internal implementation constants.
|
||||
*/
|
||||
public class Constants {
|
||||
|
||||
public static final String POJO_PATH_PARAM_KEY =
|
||||
"org.apache.tomcat.websocket.pojo.PojoEndpoint.pathParams";
|
||||
public static final String POJO_METHOD_MAPPING_KEY =
|
||||
"org.apache.tomcat.websocket.pojo.PojoEndpoint.methodMapping";
|
||||
|
||||
private Constants() {
|
||||
// Hide default constructor
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
# 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.
|
||||
|
||||
pojoEndpointBase.closeSessionFail=Failed to close WebSocket session during error handling
|
||||
pojoEndpointBase.onCloseFail=Failed to call onClose method of POJO end point for POJO of type [{0}]
|
||||
pojoEndpointBase.onError=No error handling configured for [{0}] and the following error occurred
|
||||
pojoEndpointBase.onErrorFail=Failed to call onError method of POJO end point for POJO of type [{0}]
|
||||
pojoEndpointBase.onOpenFail=Failed to call onOpen method of POJO end point for POJO of type [{0}]
|
||||
|
||||
pojoEndpointServer.getPojoInstanceFail=Failed to create instance of POJO of type [{0}]
|
||||
|
||||
pojoMessageHandlerWhole.decodeIoFail=IO error while decoding message
|
||||
pojoMessageHandlerWhole.maxBufferSize=The maximum supported message size for this implementation is Integer.MAX_VALUE
|
||||
|
||||
pojoMethodMapping.decodePathParamFail=Failed to decode path parameter value [{0}] to expected type [{1}]
|
||||
pojoMethodMapping.duplicateAnnotation=Duplicate annotations [{0}] present on class [{1}]
|
||||
pojoMethodMapping.duplicateLastParam=Multiple boolean (last) parameters present on the method [{0}] of class [{1}] that was annotated with OnMessage
|
||||
pojoMethodMapping.duplicateMessageParam=Multiple message parameters present on the method [{0}] of class [{1}] that was annotated with OnMessage
|
||||
pojoMethodMapping.duplicatePongMessageParam=Multiple PongMessage parameters present on the method [{0}] of class [{1}] that was annotated with OnMessage
|
||||
pojoMethodMapping.duplicateSessionParam=Multiple session parameters present on the method [{0}] of class [{1}] that was annotated with OnMessage
|
||||
pojoMethodMapping.invalidDecoder=The specified decoder of type [{0}] could not be instantiated
|
||||
pojoMethodMapping.methodNotPublic=The annotated method [{0}] is not public
|
||||
pojoMethodMapping.noDecoder=No decoder was found for message parameters present on the method [{0}] of class [{1}] that was annotated with OnMessage
|
||||
pojoMethodMapping.noPayload=No payload parameter present on the method [{0}] of class [{1}] that was annotated with OnMessage
|
||||
pojoMethodMapping.onErrorNoThrowable=No Throwable parameter was present on the method [{0}] of class [{1}] that was annotated with OnError
|
||||
pojoMethodMapping.paramWithoutAnnotation=A parameter of type [{0}] was found on method[{1}] of class [{2}] that did not have a @PathParam annotation
|
||||
pojoMethodMapping.partialInputStream=Invalid InputStream and boolean parameters present on the method [{0}] of class [{1}] that was annotated with OnMessage
|
||||
pojoMethodMapping.partialObject=Invalid Object and boolean parameters present on the method [{0}] of class [{1}] that was annotated with OnMessage
|
||||
pojoMethodMapping.partialPong=Invalid PongMessage and boolean parameters present on the method [{0}] of class [{1}] that was annotated with OnMessage
|
||||
pojoMethodMapping.partialReader=Invalid Reader and boolean parameters present on the method [{0}] of class [{1}] that was annotated with OnMessage
|
||||
pojoMethodMapping.pongWithPayload=Invalid PongMessage and Message parameters present on the method [{0}] of class [{1}] that was annotated with OnMessage
|
||||
|
||||
pojoPathParam.wrongType=The type [{0}] is not permitted as a path parameter. Parameters annotated with @PathParam may only be Strings, Java primitives or a boxed version thereof.
|
||||
@@ -0,0 +1,22 @@
|
||||
# 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.
|
||||
|
||||
pojoEndpointServer.getPojoInstanceFail=Es konnte keine POJO Instanz des Typs [{0}] erzeugt werden
|
||||
|
||||
pojoMethodMapping.duplicateAnnotation=Doppelte Annotation [{0}] an Klasse [{1}] gefunden
|
||||
pojoMethodMapping.duplicateLastParam=Es sind mehrere Boolean (letzte) Parameter für die Methode [{0}] der Klasse [{1}], die mit OnMessage annotiert ist, vorhanden.
|
||||
pojoMethodMapping.invalidDecoder=Der angegeben Dekoder vom Typ [{0}] konnte nicht instanziiert werden
|
||||
pojoMethodMapping.methodNotPublic=Die annotierite Methode [{0}] ist nicht öffentlich
|
||||
pojoMethodMapping.paramWithoutAnnotation=Es wurde ein Parameter des Typs [{0}] an der Methode [{1}] der Klasse [{2}] gefunden der nicht die Annotation @PathParam hat
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user