This commit is contained in:
2024-11-30 19:03:49 +08:00
commit 1e6763c160
3806 changed files with 737676 additions and 0 deletions

View 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
}
}
}
}

View 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;
}

View 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.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;
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -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);
}
}

View 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;
}
}

View 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;
}
}

View 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();
}

View 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;
}
}
}

View 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;
}
}

View 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
}
}

View 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;
}
}

View 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;
}
}

View 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;
}
}

View 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

View 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.

View 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

View 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é

View 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=書き込み操作を完了しようとすると、書き込みが進行中であることを示すフラグがfalsetrueであったはずですであることが判明しました。
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}]がレスポンスで返されました。

View 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}]이(가) 응답에서 반환되었습니다.

View 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}]

View File

@@ -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连接

View 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;
}
}

View File

@@ -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
}

View 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;
}
}

View 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();
}
}

View File

@@ -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;
}
}

View 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();
}

View 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));
}
}
}

View 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
}

File diff suppressed because it is too large Load Diff

View 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();
}

View 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();
}
}

View 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;
}
}

View 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;
}
}

File diff suppressed because it is too large Load Diff

View 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);
}
}
}
}

View 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;
}
}

View 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;
}
}

View 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;
}
}

View 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);
}
}

View 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);
}
}

View 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);
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -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();
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View 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
}
}

View 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.
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.

View File

@@ -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