Merge remote-tracking branch 'origin/master' into jetty-8

This commit is contained in:
Jan Bartel 2012-01-10 16:08:59 +11:00
commit 1fbec51c8a
46 changed files with 1680 additions and 1381 deletions

View File

@ -43,6 +43,17 @@ jetty-8.1.0.RC0 - 30 November 2011
+ 364283 can't parse the servlet multipart-config for the web.xml
+ 364430 Support web.xml enabled state for servlets
jetty-7.6.0.RC3 - 05 January 2012
+ 367433 added tests to investigate
+ 367435 improved D00 test harness
+ 367485 HttpExchange canceled before response do not release connection.
+ 367502 WebSocket connections should be closed when application context is
stopped.
+ 367591 corrected configuration.xml version to 7.6
+ 367635 Added support for start.d directory
+ 637638 limit number of form parameters to avoid DOS
+ JETTY-1467 close half closed when idle
jetty-7.6.0.RC2 - 22 December 2011
+ 364638 HttpParser closes if data received while seeking EOF. Tests fixed to
cope

View File

@ -180,20 +180,23 @@ public abstract class AbstractHttpConnection extends AbstractConnection implemen
String method=_exchange.getMethod();
String uri = _exchange.getRequestURI();
if (_destination.isProxied() && !HttpMethods.CONNECT.equals(method) && uri.startsWith("/"))
if (_destination.isProxied())
{
boolean secure = _destination.isSecure();
String host = _destination.getAddress().getHost();
int port = _destination.getAddress().getPort();
StringBuilder absoluteURI = new StringBuilder();
absoluteURI.append(secure ? HttpSchemes.HTTPS : HttpSchemes.HTTP);
absoluteURI.append("://");
absoluteURI.append(host);
// Avoid adding default ports
if (!(secure && port == 443 || !secure && port == 80))
absoluteURI.append(":").append(port);
absoluteURI.append(uri);
uri = absoluteURI.toString();
if (!HttpMethods.CONNECT.equals(method) && uri.startsWith("/"))
{
boolean secure = _destination.isSecure();
String host = _destination.getAddress().getHost();
int port = _destination.getAddress().getPort();
StringBuilder absoluteURI = new StringBuilder();
absoluteURI.append(secure ? HttpSchemes.HTTPS : HttpSchemes.HTTP);
absoluteURI.append("://");
absoluteURI.append(host);
// Avoid adding default ports
if (!(secure && port == 443 || !secure && port == 80))
absoluteURI.append(":").append(port);
absoluteURI.append(uri);
uri = absoluteURI.toString();
}
Authentication auth = _destination.getProxyAuthentication();
if (auth != null)
auth.setCredentials(_exchange);

View File

@ -0,0 +1,118 @@
// ========================================================================
// Copyright (c) 2009-2009 Mort Bay Consulting Pty. Ltd.
// ------------------------------------------------------------------------
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
// The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html
// The Apache License v2.0 is available at
// http://www.opensource.org/licenses/apache2.0.php
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
package org.eclipse.jetty.client;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.Socket;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.client.security.Authentication;
import org.eclipse.jetty.client.security.BasicAuthentication;
import org.eclipse.jetty.client.security.Realm;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.handler.ConnectHandler;
import org.eclipse.jetty.server.nio.SelectChannelConnector;
import org.junit.After;
import org.junit.Assert;
import org.junit.Assume;
import org.junit.Before;
import org.junit.Test;
public class HttpsProxyAuthenticationTest
{
private Server _proxy = new Server();
private HttpClient _client = new HttpClient();
private boolean authHandlerSend;
@Before
public void init() throws Exception
{
SelectChannelConnector connector = new SelectChannelConnector();
_proxy.addConnector(connector);
_proxy.setHandler(new ConnectHandler()
{
@Override
protected boolean handleAuthentication(HttpServletRequest request, HttpServletResponse response, String address) throws ServletException, IOException
{
String authHeader = request.getHeader("Authorization");
if (authHeader != null && authHeader.length() > 0)
authHandlerSend = true;
return super.handleAuthentication(request,response,address);
}
});
_proxy.start();
int proxyPort = connector.getLocalPort();
Authentication authentication = new BasicAuthentication(new Realm()
{
public String getId()
{
return "MyRealm";
}
public String getPrincipal()
{
return "jetty";
}
public String getCredentials()
{
return "jetty";
}
});
_client.setProxy(new Address("localhost", proxyPort));
_client.setProxyAuthentication(authentication);
_client.start();
}
@After
public void destroy() throws Exception
{
_client.stop();
_proxy.stop();
_proxy.join();
}
@Test
public void httpsViaProxyThatReturns504ErrorTest() throws Exception
{
// Assume that we can connect to google
String host = "google.com";
int port = 443;
Socket socket = new Socket();
try
{
socket.connect(new InetSocketAddress(host, port), 1000);
}
catch (IOException x)
{
Assume.assumeNoException(x);
}
finally
{
socket.close();
}
HttpExchange exchange = new ContentExchange();
exchange.setURL("https://" + host + ":" + port);
exchange.addRequestHeader("behaviour", "google");
_client.send(exchange);
Assert.assertEquals(HttpExchange.STATUS_COMPLETED, exchange.waitForDone());
Assert.assertTrue("Authorization header not set!", authHandlerSend);
}
}

View File

@ -111,6 +111,7 @@ public class ScanningAppProviderRuntimeUpdatesTest
jetty.copyWebapp("foo-webapp-1.war","foo.war");
jetty.copyContext("foo.xml","foo.xml");
waitForDirectoryScan();
waitForDirectoryScan();
jetty.assertWebAppContextsExists("/foo");
@ -125,12 +126,14 @@ public class ScanningAppProviderRuntimeUpdatesTest
jetty.copyWebapp("foo-webapp-1.war","foo.war");
jetty.copyContext("foo.xml","foo.xml");
waitForDirectoryScan();
waitForDirectoryScan();
jetty.assertWebAppContextsExists("/foo");
jetty.removeContext("foo.xml");
waitForDirectoryScan();
waitForDirectoryScan();
// FIXME: hot undeploy with removal not working! - jetty.assertNoWebAppContexts();
@ -151,6 +154,7 @@ public class ScanningAppProviderRuntimeUpdatesTest
jetty.copyWebapp("foo-webapp-1.war","foo.war");
jetty.copyContext("foo.xml","foo.xml");
waitForDirectoryScan();
waitForDirectoryScan();
jetty.assertWebAppContextsExists("/foo");
@ -165,6 +169,7 @@ public class ScanningAppProviderRuntimeUpdatesTest
// This should result in the existing foo.war being replaced with the new foo.war
waitForDirectoryScan();
waitForDirectoryScan();
jetty.assertWebAppContextsExists("/foo");
// Test that webapp response contains "-2"

View File

@ -31,6 +31,14 @@
</dependencies>
<build>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.6</source>
<target>1.6</target>
<verbose>false</verbose>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>

View File

@ -5,7 +5,6 @@
<version>8.1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-http</artifactId>
<name>Jetty :: Http Utility</name>
<properties>

View File

@ -5,7 +5,6 @@
<version>8.1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-io</artifactId>
<name>Jetty :: IO Utility</name>
<properties>

View File

@ -42,36 +42,38 @@ import org.eclipse.jetty.server.Authentication.User;
public class JaspiAuthenticator implements Authenticator
{
private final ServerAuthConfig _authConfig;
private final Map _authProperties;
private final ServletCallbackHandler _callbackHandler;
private final Subject _serviceSubject;
private final boolean _allowLazyAuthentication;
private final IdentityService _identityService;
private final DeferredAuthentication _deferred;
public JaspiAuthenticator(ServerAuthConfig authConfig, Map authProperties, ServletCallbackHandler callbackHandler,
Subject serviceSubject, boolean allowLazyAuthentication, IdentityService identityService)
public JaspiAuthenticator(ServerAuthConfig authConfig, Map authProperties, ServletCallbackHandler callbackHandler, Subject serviceSubject,
boolean allowLazyAuthentication, IdentityService identityService)
{
// TODO maybe pass this in via setConfiguration ?
if (callbackHandler == null)
throw new NullPointerException("No CallbackHandler");
if (authConfig == null)
throw new NullPointerException("No AuthConfig");
if (callbackHandler == null) throw new NullPointerException("No CallbackHandler");
if (authConfig == null) throw new NullPointerException("No AuthConfig");
this._authConfig = authConfig;
this._authProperties = authProperties;
this._callbackHandler = callbackHandler;
this._serviceSubject = serviceSubject;
this._allowLazyAuthentication = allowLazyAuthentication;
this._identityService = identityService;
this._deferred=new DeferredAuthentication(this);
this._deferred = new DeferredAuthentication(this);
}
public void setConfiguration(AuthConfiguration configuration)
{
}
public String getAuthMethod()
{
return "JASPI";
@ -79,56 +81,71 @@ public class JaspiAuthenticator implements Authenticator
public Authentication validateRequest(ServletRequest request, ServletResponse response, boolean mandatory) throws ServerAuthException
{
if (_allowLazyAuthentication && !mandatory)
return _deferred;
System.err.println("\nJaspiAuthenticator.validateRequest, uri=" + ((javax.servlet.http.HttpServletRequest) request).getRequestURI()
+ " lazy="
+ _allowLazyAuthentication
+ " mandatory="
+ mandatory);
new Throwable().printStackTrace();
JaspiMessageInfo info = new JaspiMessageInfo(request, response, mandatory);
request.setAttribute("org.eclipse.jetty.security.jaspi.info",info);
return validateRequest(info);
request.setAttribute("org.eclipse.jetty.security.jaspi.info", info);
Authentication a = validateRequest(info);
//if its not mandatory to authenticate, and the authenticator returned UNAUTHENTICATED, we treat it as authentication deferred
if (_allowLazyAuthentication && !info.isAuthMandatory() && a == Authentication.UNAUTHENTICATED)
a =_deferred;
System.err.println("JaspiAuthenticator.validateRequest returning "+a);
return a;
}
// most likely validatedUser is not needed here.
public boolean secureResponse(ServletRequest req, ServletResponse res, boolean mandatory, User validatedUser) throws ServerAuthException
{
JaspiMessageInfo info = (JaspiMessageInfo)req.getAttribute("org.eclipse.jetty.security.jaspi.info");
if (info==null) throw new NullPointerException("MeesageInfo from request missing: " + req);
return secureResponse(info,validatedUser);
System.err.println("JaspiAuthenticator.secureResponse uri=" + ((javax.servlet.http.HttpServletRequest) req).getRequestURI());
JaspiMessageInfo info = (JaspiMessageInfo) req.getAttribute("org.eclipse.jetty.security.jaspi.info");
if (info == null) throw new NullPointerException("MessageInfo from request missing: " + req);
return secureResponse(info, validatedUser);
}
public Authentication validateRequest(JaspiMessageInfo messageInfo) throws ServerAuthException
{
try
{
System.err.println("jaspAuthenticator.validateRequest(info)");
String authContextId = _authConfig.getAuthContextID(messageInfo);
ServerAuthContext authContext = _authConfig.getAuthContext(authContextId,_serviceSubject,_authProperties);
ServerAuthContext authContext = _authConfig.getAuthContext(authContextId, _serviceSubject, _authProperties);
Subject clientSubject = new Subject();
AuthStatus authStatus = authContext.validateRequest(messageInfo,clientSubject,_serviceSubject);
// String authMethod = (String)messageInfo.getMap().get(JaspiMessageInfo.AUTH_METHOD_KEY);
AuthStatus authStatus = authContext.validateRequest(messageInfo, clientSubject, _serviceSubject);
// String authMethod =
// (String)messageInfo.getMap().get(JaspiMessageInfo.AUTH_METHOD_KEY);
if (authStatus == AuthStatus.SEND_CONTINUE) return Authentication.SEND_CONTINUE;
if (authStatus == AuthStatus.SEND_FAILURE) return Authentication.SEND_FAILURE;
if (authStatus == AuthStatus.SEND_CONTINUE)
return Authentication.SEND_CONTINUE;
if (authStatus == AuthStatus.SEND_FAILURE)
return Authentication.SEND_FAILURE;
if (authStatus == AuthStatus.SUCCESS)
{
Set<UserIdentity> ids = clientSubject.getPrivateCredentials(UserIdentity.class);
Set<UserIdentity> ids = clientSubject.getPrivateCredentials(UserIdentity.class);
UserIdentity userIdentity;
if (ids.size() > 0)
{
userIdentity = ids.iterator().next();
} else {
}
else
{
CallerPrincipalCallback principalCallback = _callbackHandler.getThreadCallerPrincipalCallback();
if (principalCallback == null)
{
return Authentication.UNAUTHENTICATED;
}
if (principalCallback == null) { return Authentication.UNAUTHENTICATED; }
Principal principal = principalCallback.getPrincipal();
if (principal == null) {
if (principal == null)
{
String principalName = principalCallback.getName();
Set<Principal> principals = principalCallback.getSubject().getPrincipals();
for (Principal p: principals)
for (Principal p : principals)
{
if (p.getName().equals(principalName))
{
@ -136,10 +153,7 @@ public class JaspiAuthenticator implements Authenticator
break;
}
}
if (principal == null)
{
return Authentication.UNAUTHENTICATED;
}
if (principal == null) { return Authentication.UNAUTHENTICATED; }
}
GroupPrincipalCallback groupPrincipalCallback = _callbackHandler.getThreadGroupPrincipalCallback();
String[] groups = groupPrincipalCallback == null ? null : groupPrincipalCallback.getGroups();
@ -149,10 +163,10 @@ public class JaspiAuthenticator implements Authenticator
}
if (authStatus == AuthStatus.SEND_SUCCESS)
{
//we are processing a message in a secureResponse dialog.
// we are processing a message in a secureResponse dialog.
return Authentication.SEND_SUCCESS;
}
//should not happen
// should not happen
throw new NullPointerException("No AuthStatus returned");
}
catch (AuthException e)
@ -166,13 +180,16 @@ public class JaspiAuthenticator implements Authenticator
try
{
String authContextId = _authConfig.getAuthContextID(messageInfo);
ServerAuthContext authContext = _authConfig.getAuthContext(authContextId,_serviceSubject,_authProperties);
// TODO authContext.cleanSubject(messageInfo,validatedUser.getUserIdentity().getSubject());
AuthStatus status = authContext.secureResponse(messageInfo,_serviceSubject);
ServerAuthContext authContext = _authConfig.getAuthContext(authContextId, _serviceSubject, _authProperties);
// TODO
// authContext.cleanSubject(messageInfo,validatedUser.getUserIdentity().getSubject());
AuthStatus status = authContext.secureResponse(messageInfo, _serviceSubject);
return (AuthStatus.SEND_SUCCESS.equals(status));
}
catch (AuthException e)
{
System.err.println("Error in JaspiAuthenticator.secureResponse");
e.printStackTrace();
throw new ServerAuthException(e);
}
}

View File

@ -98,9 +98,13 @@ public class JaspiAuthenticatorFactory extends DefaultAuthenticatorFactory
Subject serviceSubject=findServiceSubject(server);
String serverName=findServerName(server,serviceSubject);
System.err.println("authconfigfactory="+authConfigFactory+" serviceSubject="+serviceSubject+" serverName="+serverName);
String appContext = serverName + " " + context.getContextPath();
System.err.println("appcontext="+appContext);
AuthConfigProvider authConfigProvider = authConfigFactory.getConfigProvider(MESSAGE_LAYER,appContext,listener);
System.err.println("authconfigProvider="+authConfigProvider);
if (authConfigProvider != null)
{
ServletCallbackHandler servletCallbackHandler = new ServletCallbackHandler(loginService);

View File

@ -90,8 +90,9 @@ public class ServletCallbackHandler implements CallbackHandler
if (user!=null)
{
loginCallback.setUserPrincipal(user.getUserPrincipal());
credentialValidationCallback.getSubject().getPrivateCredentials().add(loginCallback);
credentialValidationCallback.setResult(true);
credentialValidationCallback.getSubject().getPrincipals().addAll(user.getSubject().getPrincipals());
credentialValidationCallback.getSubject().getPrivateCredentials().add(user);
}

View File

@ -90,12 +90,12 @@ public class BaseAuthModule implements ServerAuthModule, ServerAuthContext
public AuthStatus secureResponse(MessageInfo messageInfo, Subject serviceSubject) throws AuthException
{
// servlets do not need secured responses
return AuthStatus.SUCCESS;
return AuthStatus.SEND_SUCCESS;
}
public AuthStatus validateRequest(MessageInfo messageInfo, Subject clientSubject, Subject serviceSubject) throws AuthException
{
return AuthStatus.FAILURE;
return AuthStatus.SEND_FAILURE;
}
/**
@ -131,6 +131,7 @@ public class BaseAuthModule implements ServerAuthModule, ServerAuthContext
if (credValidationCallback.getResult())
{
Set<LoginCallbackImpl> loginCallbacks = clientSubject.getPrivateCredentials(LoginCallbackImpl.class);
System.err.println("LoginCallbackImpls.isEmpty="+loginCallbacks.isEmpty());
if (!loginCallbacks.isEmpty())
{
LoginCallbackImpl loginCallback = loginCallbacks.iterator().next();

View File

@ -36,7 +36,9 @@ import javax.servlet.http.HttpSessionBindingListener;
import org.eclipse.jetty.util.security.Constraint;
import org.eclipse.jetty.util.security.Password;
import org.eclipse.jetty.security.CrossContextPsuedoSession;
import org.eclipse.jetty.security.authentication.DeferredAuthentication;
import org.eclipse.jetty.security.authentication.LoginCallbackImpl;
import org.eclipse.jetty.server.Authentication;
import org.eclipse.jetty.util.StringUtil;
import org.eclipse.jetty.util.URIUtil;
import org.eclipse.jetty.util.log.Log;
@ -146,37 +148,50 @@ public class FormAuthModule extends BaseAuthModule
@Override
public AuthStatus validateRequest(MessageInfo messageInfo, Subject clientSubject, Subject serviceSubject) throws AuthException
{
HttpServletRequest request = (HttpServletRequest) messageInfo.getRequestMessage();
HttpServletResponse response = (HttpServletResponse) messageInfo.getResponseMessage();
HttpSession session = request.getSession(isMandatory(messageInfo));
String uri = request.getPathInfo();
// not mandatory and not authenticated
if (session == null || isLoginOrErrorPage(uri)) return AuthStatus.SUCCESS;
String uri = request.getRequestURI();
if (uri==null)
uri=URIUtil.SLASH;
boolean mandatory = isMandatory(messageInfo);
mandatory |= isJSecurityCheck(uri);
HttpSession session = request.getSession(mandatory);
System.err.println("FormAuthModule.validateRequest(info,subject,serviceSubject) for uri="+uri+" mandatory="+mandatory+" isLoginOrError="+isLoginOrErrorPage(URIUtil.addPaths(request.getServletPath(),request.getPathInfo())));
// not mandatory or its the login or login error page don't authenticate
if (!mandatory || isLoginOrErrorPage(URIUtil.addPaths(request.getServletPath(),request.getPathInfo()))) return AuthStatus.SUCCESS;
try
{
// Handle a request for authentication.
// TODO perhaps j_securitycheck can be uri suffix?
if (uri.endsWith(__J_SECURITY_CHECK))
if (isJSecurityCheck(uri))
{
final String username = request.getParameter(__J_USERNAME);
final String password = request.getParameter(__J_PASSWORD);
System.err.println("Try login username="+username+" password="+password);
boolean success = tryLogin(messageInfo, clientSubject, response, session, username, new Password(password));
if (success)
{
// Redirect to original request
String nuri = (String) session.getAttribute(__J_URI);
// Redirect to original request
String nuri=null;
synchronized(session)
{
nuri = (String) session.getAttribute(__J_URI);
}
if (nuri == null || nuri.length() == 0)
{
nuri = request.getContextPath();
if (nuri.length() == 0) nuri = URIUtil.SLASH;
if (nuri.length() == 0)
nuri = URIUtil.SLASH;
}
session.removeAttribute(__J_URI); // Remove popped return
// URI.
response.setContentLength(0);
System.err.println("FormAuthModule succesful login, sending redirect to "+nuri);
response.setContentLength(0);
response.sendRedirect(response.encodeRedirectURL(nuri));
return AuthStatus.SEND_CONTINUE;
}
// not authenticated
@ -194,95 +209,18 @@ public class FormAuthModule extends BaseAuthModule
// that occur?
return AuthStatus.SEND_FAILURE;
}
// Check if the session is already authenticated.
FormCredential form_cred = (FormCredential) session.getAttribute(__J_AUTHENTICATED);
if (form_cred != null)
{
System.err.println("Form cred: form.username="+form_cred._jUserName+" form.pwd="+new String(form_cred._jPassword));
//TODO: we would like the form auth module to be able to invoke the loginservice.validate() method to check the previously authed user
boolean success = tryLogin(messageInfo, clientSubject, response, session, form_cred._jUserName, new Password(new String(form_cred._jPassword)));
if (success) { return AuthStatus.SUCCESS; }
// CallbackHandler loginCallbackHandler = new
// UserPasswordCallbackHandler(form_cred._jUserName,
// form_cred._jPassword);
// LoginResult loginResult = loginService.login(clientSubject,
// loginCallbackHandler);
// //TODO what should happen if !isMandatory but credentials
// exist and are wrong?
// if (loginResult.isSuccess())
// {
// callbackHandler.handle(new
// Callback[]{loginResult.getCallerPrincipalCallback(),
// loginResult.getGroupPrincipalCallback()});
// messageInfo.getMap().put(JettyMessageInfo.AUTH_METHOD_KEY,
// Constraint.__FORM_AUTH);
//
// form_cred = new FormCredential(form_cred._jUserName,
// form_cred._jPassword,
// loginResult.getCallerPrincipalCallback().getPrincipal());
//
// session.setAttribute(__J_AUTHENTICATED, form_cred);
// if (ssoSource != null && ssoSource.fetch(request) == null)
// {
// UserInfo userInfo = new UserInfo(form_cred._jUserName,
// form_cred._jPassword);
// ssoSource.store(userInfo, response);
// }
// messageInfo.getMap().put(JettyMessageInfo.AUTH_METHOD_KEY,
// Constraint.__FORM_AUTH);
// return AuthStatus.SUCCESS;
// }
// // We have a form credential. Has it been distributed?
// if (form_cred._userPrincipal==null)
// {
// // This form_cred appears to have been distributed. Need to
// reauth
// form_cred.authenticate(realm, request);
//
// // Sign-on to SSO mechanism
// if (form_cred._userPrincipal!=null && realm instanceof
// SSORealm)
// ((SSORealm)realm).setSingleSignOn(request,response,form_cred._userPrincipal,new
// Password(form_cred._jPassword));
//
// }
// else if (!realm.reauthenticate(form_cred._userPrincipal))
// // Else check that it is still authenticated.
// form_cred._userPrincipal=null;
//
// // If this credential is still authenticated
// if (form_cred._userPrincipal!=null)
// {
// if(LOG.isDebugEnabled())LOG.debug("FORM Authenticated for
// "+form_cred._userPrincipal.getName());
// request.setAuthType(Constraint.__FORM_AUTH);
// //jaspi
// // request.setUserPrincipal(form_cred._userPrincipal);
// return form_cred._userPrincipal;
// }
// else
// session.setAttribute(__J_AUTHENTICATED,null);
// }
// else if (realm instanceof SSORealm)
// {
// // Try a single sign on.
// Credential cred =
// ((SSORealm)realm).getSingleSignOn(request,response);
//
// if (request.getUserPrincipal()!=null)
// {
// form_cred=new FormCredential();
// form_cred._userPrincipal=request.getUserPrincipal();
// form_cred._jUserName=form_cred._userPrincipal.getName();
// if (cred!=null)
// form_cred._jPassword=cred.toString();
// if(LOG.isDebugEnabled())LOG.debug("SSO for
// "+form_cred._userPrincipal);
//
// request.setAuthType(Constraint.__FORM_AUTH);
// session.setAttribute(__J_AUTHENTICATED,form_cred);
// return form_cred._userPrincipal;
// }
}
else if (ssoSource != null)
{
@ -293,19 +231,25 @@ public class FormAuthModule extends BaseAuthModule
if (success) { return AuthStatus.SUCCESS; }
}
}
// Don't authenticate authform or errorpage
if (!isMandatory(messageInfo) || isLoginOrErrorPage(uri))
// TODO verify this is correct action
return AuthStatus.SUCCESS;
// if we can't send challenge
if (DeferredAuthentication.isDeferred(response))
return AuthStatus.SUCCESS;
// redirect to login page
if (request.getQueryString() != null) uri += "?" + request.getQueryString();
session.setAttribute(__J_URI, request.getScheme() + "://"
+ request.getServerName()
+ ":"
+ request.getServerPort()
+ URIUtil.addPaths(request.getContextPath(), uri));
// redirect to login page
StringBuffer buf = request.getRequestURL();
if (request.getQueryString() != null)
buf.append("?").append(request.getQueryString());
synchronized (session)
{
session.setAttribute(__J_URI, buf.toString());
}
System.err.println("Redirecting to login page "+_formLoginPage+" and remembering juri="+buf.toString());
response.setContentLength(0);
response.sendRedirect(response.encodeRedirectURL(URIUtil.addPaths(request.getContextPath(), _formLoginPage)));
return AuthStatus.SEND_CONTINUE;
@ -320,6 +264,20 @@ public class FormAuthModule extends BaseAuthModule
}
}
/* ------------------------------------------------------------ */
public boolean isJSecurityCheck(String uri)
{
int jsc = uri.indexOf(__J_SECURITY_CHECK);
if (jsc<0)
return false;
int e=jsc+__J_SECURITY_CHECK.length();
if (e==uri.length())
return true;
char c = uri.charAt(e);
return c==';'||c=='#'||c=='/'||c=='?';
}
private boolean tryLogin(MessageInfo messageInfo, Subject clientSubject,
HttpServletResponse response, HttpSession session,
@ -330,10 +288,11 @@ public class FormAuthModule extends BaseAuthModule
{
char[] pwdChars = password.toString().toCharArray();
Set<LoginCallbackImpl> loginCallbacks = clientSubject.getPrivateCredentials(LoginCallbackImpl.class);
System.err.println("FormAuthModule, LoginCallbackImpl.isEmpty="+loginCallbacks.isEmpty());
if (!loginCallbacks.isEmpty())
{
LoginCallbackImpl loginCallback = loginCallbacks.iterator().next();
FormCredential form_cred = new FormCredential(username, pwdChars, loginCallback.getUserPrincipal());
FormCredential form_cred = new FormCredential(username, pwdChars, loginCallback.getUserPrincipal(), loginCallback.getSubject());
session.setAttribute(__J_AUTHENTICATED, form_cred);
}
@ -347,38 +306,11 @@ public class FormAuthModule extends BaseAuthModule
return true;
}
return false;
// LoginCallback loginCallback = new LoginCallback(clientSubject,
// username, password);
// loginService.login(loginCallback);
// if (loginCallback.isSuccess())
// {
// CallerPrincipalCallback callerPrincipalCallback = new
// CallerPrincipalCallback(clientSubject,
// loginCallback.getUserPrincipal());
// GroupPrincipalCallback groupPrincipalCallback = new
// GroupPrincipalCallback(clientSubject,
// loginCallback.getGroups().toArray(new
// String[loginCallback.getGroups().size()]));
// callbackHandler.handle(new Callback[] {callerPrincipalCallback,
// groupPrincipalCallback});
// messageInfo.getMap().put(JettyMessageInfo.AUTH_METHOD_KEY,
// Constraint.__FORM_AUTH);
// FormCredential form_cred = new FormCredential(username, password,
// loginCallback.getUserPrincipal());
//
// session.setAttribute(__J_AUTHENTICATED, form_cred);
// // Sign-on to SSO mechanism
// if (ssoSource != null)
// {
// UserInfo userInfo = new UserInfo(username, password);
// ssoSource.store(userInfo, response);
// }
// }
// return loginCallback.isSuccess();
}
public boolean isLoginOrErrorPage(String pathInContext)
{
System.err.println("ISLOGINORERRORPAGE? "+pathInContext+" error: "+_formErrorPath+" login:"+_formLoginPath);
return pathInContext != null && (pathInContext.equals(_formErrorPath) || pathInContext.equals(_formLoginPath));
}
@ -393,12 +325,15 @@ public class FormAuthModule extends BaseAuthModule
char[] _jPassword;
transient Principal _userPrincipal;
transient Subject _subject;
private FormCredential(String _jUserName, char[] _jPassword, Principal _userPrincipal)
private FormCredential(String _jUserName, char[] _jPassword, Principal _userPrincipal, Subject subject)
{
this._jUserName = _jUserName;
this._jPassword = _jPassword;
this._userPrincipal = _userPrincipal;
this._subject = subject;
}
public void valueBound(HttpSessionBindingEvent event)

View File

@ -6,7 +6,6 @@
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>org.eclipse.jetty.osgi</groupId>
<artifactId>jetty-osgi-boot-jsp</artifactId>
<name>Jetty :: OSGi :: Boot JSP</name>
<description>Jetty OSGi Boot JSP bundle</description>

View File

@ -6,7 +6,6 @@
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>org.eclipse.jetty.osgi</groupId>
<artifactId>jetty-osgi-boot-warurl</artifactId>
<name>Jetty :: OSGi :: Boot :: Warurl</name>
<description>Jetty OSGi Boot-Warurl bundle</description>

View File

@ -6,7 +6,6 @@
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>org.eclipse.jetty.osgi</groupId>
<artifactId>jetty-osgi-boot</artifactId>
<name>Jetty :: OSGi :: Boot</name>
<description>Jetty OSGi Boot bundle</description>

View File

@ -6,7 +6,6 @@
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>org.eclipse.jetty.osgi</groupId>
<artifactId>jetty-httpservice</artifactId>
<name>Jetty :: OSGi :: HttpService</name>
<description>Jetty OSGi HttpService bundle</description>

View File

@ -6,7 +6,6 @@
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>org.eclipse.jetty.osgi</groupId>
<artifactId>test-jetty-osgi</artifactId>
<name>Jetty :: OSGi :: Test</name>
<description>Jetty OSGi Integration test</description>

View File

@ -5,7 +5,6 @@
<artifactId>jetty-project</artifactId>
<version>8.1.0-SNAPSHOT</version>
</parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-policy</artifactId>
<name>Jetty :: Policy Tool</name>
<packaging>jar</packaging>

View File

@ -318,11 +318,13 @@ public abstract class SecurityHandler extends HandlerWrapper implements Authenti
if (!_loginServiceShared && _loginService instanceof LifeCycle)
((LifeCycle)_loginService).start();
System.err.println("authenticator="+_authenticator+" authenticatorFactory="+_authenticatorFactory+" identityService="+_identityService);
if (_authenticator==null && _authenticatorFactory!=null && _identityService!=null)
{
_authenticator=_authenticatorFactory.getAuthenticator(getServer(),ContextHandler.getCurrentContext(),this, _identityService, _loginService);
if (_authenticator!=null)
_authMethod=_authenticator.getAuthMethod();
System.err.println("Called auth factory, authenticator="+_authenticator);
}
if (_authenticator==null)
@ -477,7 +479,7 @@ public abstract class SecurityHandler extends HandlerWrapper implements Authenti
deferred.setIdentityService(_identityService);
deferred.setLoginService(_loginService);
baseRequest.setAuthentication(authentication);
System.err.println("uri="+baseRequest.getUri()+" Auth is deferred");
try
{
handler.handle(pathInContext, baseRequest, request, response);
@ -487,7 +489,7 @@ public abstract class SecurityHandler extends HandlerWrapper implements Authenti
previousIdentity = deferred.getPreviousAssociation();
deferred.setIdentityService(null);
}
System.err.println("Securityhandler calling secureResponse, for Authentication.User");
Authentication auth=baseRequest.getAuthentication();
if (auth instanceof Authentication.User)
{

View File

@ -169,7 +169,7 @@ public class DeferredAuthentication implements Authentication.Deferred
* @param response
* @return true if this response is from a deferred call to {@link #authenticate(ServletRequest)}
*/
public boolean isDeferred(HttpServletResponse response)
public static boolean isDeferred(HttpServletResponse response)
{
return response==__deferredResponse;
}
@ -177,7 +177,7 @@ public class DeferredAuthentication implements Authentication.Deferred
/* ------------------------------------------------------------ */
/* ------------------------------------------------------------ */
/* ------------------------------------------------------------ */
static HttpServletResponse __deferredResponse = new HttpServletResponse()
final static HttpServletResponse __deferredResponse = new HttpServletResponse()
{
public void addCookie(Cookie cookie)
{

View File

@ -216,9 +216,6 @@ public class AsyncContinuation implements AsyncContext, Continuation
}
/* ------------------------------------------------------------ */
/* (non-Javadoc)
* @see javax.servlet.ServletRequest#isSuspended()
*/
public boolean isSuspending()
{
synchronized(this)

View File

@ -126,10 +126,10 @@ public class AsyncHttpConnection extends AbstractHttpConnection implements Async
}
else if (_request.getAsyncContinuation().isAsyncStarted())
{
// The request is suspended, so even though progress has been made, break the while loop
// The request is suspended, so even though progress has been made,
// exit the while loop by setting progress to false
LOG.debug("suspended {}",this);
// TODO: breaking inside finally blocks is bad: rethink how we should exit from here
break;
progress=false;
}
}
}
@ -139,16 +139,19 @@ public class AsyncHttpConnection extends AbstractHttpConnection implements Async
setCurrentConnection(null);
// If we are not suspended
if (!_request.isAsyncStarted())
if (!_request.getAsyncContinuation().isAsyncStarted())
{
// return buffers
_parser.returnBuffers();
_generator.returnBuffers();
// resuming checking for idle
}
// reenable idle checking unless request is suspended
if(!_request.getAsyncContinuation().isAsyncStarted())
{
_asyncEndp.setCheckForIdle(true);
}
// Safety net to catch spinning
if (some_progress)
_total_no_progress=0;

View File

@ -39,6 +39,9 @@ import static org.junit.matchers.JUnitMatchers.containsString;
public abstract class ConnectorTimeoutTest extends HttpServerTestFixture
{
protected static final int MAX_IDLE_TIME=250;
private int sleepTime = MAX_IDLE_TIME + MAX_IDLE_TIME/5;
private int minimumTestRuntime = MAX_IDLE_TIME-MAX_IDLE_TIME/5;
private int maximumTestRuntime = MAX_IDLE_TIME*10;
static
{
@ -68,11 +71,11 @@ public abstract class ConnectorTimeoutTest extends HttpServerTestFixture
long start = System.currentTimeMillis();
IO.toString(is);
Thread.sleep(300);
Thread.sleep(sleepTime);
assertEquals(-1, is.read());
Assert.assertTrue(System.currentTimeMillis()-start>200);
Assert.assertTrue(System.currentTimeMillis()-start<5000);
Assert.assertTrue(System.currentTimeMillis()-start>minimumTestRuntime);
Assert.assertTrue(System.currentTimeMillis()-start<maximumTestRuntime);
}
@Test
@ -101,11 +104,11 @@ public abstract class ConnectorTimeoutTest extends HttpServerTestFixture
long start = System.currentTimeMillis();
IO.toString(is);
Thread.sleep(300);
Thread.sleep(sleepTime);
assertEquals(-1, is.read());
Assert.assertTrue(System.currentTimeMillis()-start>200);
Assert.assertTrue(System.currentTimeMillis()-start<5000);
Assert.assertTrue(System.currentTimeMillis()-start>minimumTestRuntime);
Assert.assertTrue(System.currentTimeMillis()-start<maximumTestRuntime);
}
@Test
@ -126,7 +129,7 @@ public abstract class ConnectorTimeoutTest extends HttpServerTestFixture
{}
super.handle(target,baseRequest,request,response);
}
});
Socket client=newSocket(HOST,_connector.getLocalPort());
client.setSoTimeout(10000);
@ -151,14 +154,14 @@ public abstract class ConnectorTimeoutTest extends HttpServerTestFixture
// read the response
String result=IO.toString(is);
Assert.assertThat("OK",result,containsString("200 OK"));
// check client reads EOF
assertEquals(-1, is.read());
// wait for idle timeout
TimeUnit.MILLISECONDS.sleep(MAX_IDLE_TIME+MAX_IDLE_TIME/2);
// further writes will get broken pipe or similar
try
{
@ -199,7 +202,7 @@ public abstract class ConnectorTimeoutTest extends HttpServerTestFixture
{}
super.handle(target,baseRequest,request,response);
}
});
Socket client=newSocket(HOST,_connector.getLocalPort());
client.setSoTimeout(10000);
@ -220,10 +223,10 @@ public abstract class ConnectorTimeoutTest extends HttpServerTestFixture
"\r\n").getBytes("utf-8"));
os.write(contentB);
os.flush();
// Get the server side endpoint
EndPoint endp = endpoint.exchange(null,10,TimeUnit.SECONDS);
// read the response
IO.toString(is);
@ -232,7 +235,7 @@ public abstract class ConnectorTimeoutTest extends HttpServerTestFixture
TimeUnit.MILLISECONDS.sleep(MAX_IDLE_TIME+MAX_IDLE_TIME/2);
// further writes will get broken pipe or similar
try
{
@ -251,7 +254,7 @@ public abstract class ConnectorTimeoutTest extends HttpServerTestFixture
{
// expected
}
// check the server side is closed
Assert.assertFalse(endp.isOpen());
}
@ -266,7 +269,7 @@ public abstract class ConnectorTimeoutTest extends HttpServerTestFixture
InputStream is=client.getInputStream();
assertFalse(client.isClosed());
Thread.sleep(500);
Thread.sleep(sleepTime);
long start = System.currentTimeMillis();
try
{
@ -281,7 +284,7 @@ public abstract class ConnectorTimeoutTest extends HttpServerTestFixture
{
e.printStackTrace();
}
Assert.assertTrue(System.currentTimeMillis()-start<5000);
Assert.assertTrue(System.currentTimeMillis()-start<maximumTestRuntime);
}

View File

@ -200,288 +200,12 @@ public class LocalAsyncContextTest
return ((LocalConnector)_connector).getResponses(request);
}
private static class SuspendHandler extends HandlerWrapper
{
private int _read;
private long _suspendFor=-1;
private long _resumeAfter=-1;
private long _completeAfter=-1;
private long _suspendFor2=-1;
private long _resumeAfter2=-1;
private long _completeAfter2=-1;
public SuspendHandler()
{
}
public int getRead()
{
return _read;
}
public void setRead(int read)
{
_read = read;
}
public long getSuspendFor()
{
return _suspendFor;
}
public void setSuspendFor(long suspendFor)
{
_suspendFor = suspendFor;
}
public long getResumeAfter()
{
return _resumeAfter;
}
public void setResumeAfter(long resumeAfter)
{
_resumeAfter = resumeAfter;
}
public long getCompleteAfter()
{
return _completeAfter;
}
public void setCompleteAfter(long completeAfter)
{
_completeAfter = completeAfter;
}
/* ------------------------------------------------------------ */
/** Get the suspendFor2.
* @return the suspendFor2
*/
public long getSuspendFor2()
{
return _suspendFor2;
}
/* ------------------------------------------------------------ */
/** Set the suspendFor2.
* @param suspendFor2 the suspendFor2 to set
*/
public void setSuspendFor2(long suspendFor2)
{
_suspendFor2 = suspendFor2;
}
/* ------------------------------------------------------------ */
/** Get the resumeAfter2.
* @return the resumeAfter2
*/
public long getResumeAfter2()
{
return _resumeAfter2;
}
/* ------------------------------------------------------------ */
/** Set the resumeAfter2.
* @param resumeAfter2 the resumeAfter2 to set
*/
public void setResumeAfter2(long resumeAfter2)
{
_resumeAfter2 = resumeAfter2;
}
/* ------------------------------------------------------------ */
/** Get the completeAfter2.
* @return the completeAfter2
*/
public long getCompleteAfter2()
{
return _completeAfter2;
}
/* ------------------------------------------------------------ */
/** Set the completeAfter2.
* @param completeAfter2 the completeAfter2 to set
*/
public void setCompleteAfter2(long completeAfter2)
{
_completeAfter2 = completeAfter2;
}
@Override
public void handle(String target, final Request baseRequest, final HttpServletRequest request, final HttpServletResponse response) throws IOException, ServletException
{
try
{
if (DispatcherType.REQUEST.equals(baseRequest.getDispatcherType()))
{
if (_read>0)
{
byte[] buf=new byte[_read];
request.getInputStream().read(buf);
}
else if (_read<0)
{
InputStream in = request.getInputStream();
int b=in.read();
while(b!=-1)
b=in.read();
}
final AsyncContext asyncContext = baseRequest.startAsync();
response.getOutputStream().println("STARTASYNC");
asyncContext.addListener(__asyncListener);
asyncContext.addListener(__asyncListener1);
if (_suspendFor>0)
asyncContext.setTimeout(_suspendFor);
if (_completeAfter>0)
{
new Thread() {
@Override
public void run()
{
try
{
Thread.sleep(_completeAfter);
response.getOutputStream().println("COMPLETED");
response.setStatus(200);
baseRequest.setHandled(true);
asyncContext.complete();
}
catch(Exception e)
{
e.printStackTrace();
}
}
}.start();
}
else if (_completeAfter==0)
{
response.getOutputStream().println("COMPLETED");
response.setStatus(200);
baseRequest.setHandled(true);
asyncContext.complete();
}
if (_resumeAfter>0)
{
new Thread() {
@Override
public void run()
{
try
{
Thread.sleep(_resumeAfter);
if(((HttpServletRequest)asyncContext.getRequest()).getSession(true).getId()!=null)
asyncContext.dispatch();
}
catch(Exception e)
{
e.printStackTrace();
}
}
}.start();
}
else if (_resumeAfter==0)
{
asyncContext.dispatch();
}
}
else
{
if (request.getAttribute("TIMEOUT")!=null)
response.getOutputStream().println("TIMEOUT");
else
response.getOutputStream().println("DISPATCHED");
if (_suspendFor2>=0)
{
final AsyncContext asyncContext = baseRequest.startAsync();
response.getOutputStream().println("STARTASYNC2");
if (_suspendFor2>0)
asyncContext.setTimeout(_suspendFor2);
_suspendFor2=-1;
if (_completeAfter2>0)
{
new Thread() {
@Override
public void run()
{
try
{
Thread.sleep(_completeAfter2);
response.getOutputStream().println("COMPLETED2");
response.setStatus(200);
baseRequest.setHandled(true);
asyncContext.complete();
}
catch(Exception e)
{
e.printStackTrace();
}
}
}.start();
}
else if (_completeAfter2==0)
{
response.getOutputStream().println("COMPLETED2");
response.setStatus(200);
baseRequest.setHandled(true);
asyncContext.complete();
}
if (_resumeAfter2>0)
{
new Thread() {
@Override
public void run()
{
try
{
Thread.sleep(_resumeAfter2);
asyncContext.dispatch();
}
catch(Exception e)
{
e.printStackTrace();
}
}
}.start();
}
else if (_resumeAfter2==0)
{
asyncContext.dispatch();
}
}
else
{
response.setStatus(200);
baseRequest.setHandled(true);
}
}
}
finally
{
}
}
}
static AtomicInteger __completed = new AtomicInteger();
static AtomicInteger __completed1 = new AtomicInteger();
private static AsyncListener __asyncListener = new AsyncListener()
static AsyncListener __asyncListener = new AsyncListener()
{
@Override
@ -512,7 +236,7 @@ public class LocalAsyncContextTest
};
private static AsyncListener __asyncListener1 = new AsyncListener()
static AsyncListener __asyncListener1 = new AsyncListener()
{
@Override

View File

@ -40,6 +40,7 @@ import junit.framework.Assert;
import org.eclipse.jetty.http.MimeTypes;
import org.eclipse.jetty.server.handler.AbstractHandler;
import org.eclipse.jetty.server.handler.ContextHandler;
import org.eclipse.jetty.util.IO;
import org.eclipse.jetty.util.StringUtil;
import org.eclipse.jetty.util.log.Log;
@ -78,7 +79,7 @@ public class RequestTest
_server.stop();
_server.join();
}
@Test
public void testParamExtraction() throws Exception
{
@ -101,27 +102,27 @@ public class RequestTest
System.err.println(map);
assertFalse(map == null);
assertTrue(map.isEmpty());
Enumeration names = request.getParameterNames();
assertFalse(names.hasMoreElements());
}
return true;
}
};
//Send a request with query string with illegal hex code to cause
//an exception parsing the params
String request="GET /?param=%ZZaaa HTTP/1.1\r\n"+
"Host: whatever\r\n"+
"Content-Type: text/html;charset=utf8\n"+
"\n";
String responses=_connector.getResponses(request);
assertTrue(responses.startsWith("HTTP/1.1 200"));
}
@Test
public void testBadUtf8ParamExtraction() throws Exception
{
@ -133,20 +134,40 @@ public class RequestTest
return value.startsWith("aaa") && value.endsWith("bb");
}
};
//Send a request with query string with illegal hex code to cause
//an exception parsing the params
String request="GET /?param=aaa%E7bbb HTTP/1.1\r\n"+
"Host: whatever\r\n"+
"Content-Type: text/html;charset=utf8\n"+
"\n";
String responses=_connector.getResponses(request);
assertTrue(responses.startsWith("HTTP/1.1 200"));
assertTrue(responses.startsWith("HTTP/1.1 200"));
}
@Test
public void testInvalidHostHeader() throws Exception
{
// Use a contextHandler with vhosts to force call to Request.getServerName()
ContextHandler handler = new ContextHandler();
handler.addVirtualHosts(new String[1]);
_server.stop();
_server.setHandler(handler);
_server.start();
// Request with illegal Host header
String request="GET / HTTP/1.1\r\n"+
"Host: whatever.com:\r\n"+
"Content-Type: text/html;charset=utf8\n"+
"\n";
String responses=_connector.getResponses(request);
assertTrue("400 Bad Request response expected",responses.startsWith("HTTP/1.1 400"));
}
@Test
public void testContentTypeEncoding() throws Exception
{
@ -196,7 +217,7 @@ public class RequestTest
assertTrue(results.get(i++).startsWith("text/html"));
assertEquals(" x=z; ",results.get(i++));
}
@Test
public void testHostPort() throws Exception
{
@ -369,7 +390,7 @@ public class RequestTest
Reader reader=request.getReader();
String in = IO.toString(reader);
String param = request.getParameter("param");
byte[] b=("read='"+in+"' param="+param+"\n").getBytes(StringUtil.__UTF8);
response.setContentLength(b.length);
response.getOutputStream().write(b);
@ -389,11 +410,11 @@ public class RequestTest
"param=wrong\r\n";
String responses = _connector.getResponses(request);
assertTrue(responses.indexOf("read='param=wrong' param=right")>0);
}
@Test
public void testPartialInput() throws Exception
{
@ -754,7 +775,7 @@ public class RequestTest
{
_server.setAttribute("org.eclipse.jetty.server.Request.maxFormContentSize",-1);
_server.setAttribute("org.eclipse.jetty.server.Request.maxFormKeys",1000);
// This file is not distributed - as it is dangerous
File evil_keys = new File("/tmp/keys_mapping_to_zero_2m");
if (!evil_keys.exists())
@ -762,10 +783,10 @@ public class RequestTest
Log.info("testHashDOS skipped");
return;
}
BufferedReader in = new BufferedReader(new FileReader(evil_keys));
StringBuilder buf = new StringBuilder(4000000);
String key=null;
buf.append("a=b");
while((key=in.readLine())!=null)
@ -773,7 +794,7 @@ public class RequestTest
buf.append("&").append(key).append("=").append("x");
}
buf.append("&c=d");
_handler._checker = new RequestTester()
{
public boolean check(HttpServletRequest request,HttpServletResponse response)
@ -789,15 +810,15 @@ public class RequestTest
"Connection: close\r\n"+
"\r\n"+
buf;
long start=System.currentTimeMillis();
String response = _connector.getResponses(request);
assertTrue(response.contains("200 OK"));
long now=System.currentTimeMillis();
assertTrue((now-start)<5000);
}
interface RequestTester
{
boolean check(HttpServletRequest request,HttpServletResponse response) throws IOException;
@ -814,12 +835,12 @@ public class RequestTest
if (request.getContentLength()>0 && !MimeTypes.FORM_ENCODED.equals(request.getContentType()))
_content=IO.toString(request.getInputStream());
if (_checker!=null && _checker.check(request,response))
response.setStatus(200);
else
response.sendError(500);
}
}

View File

@ -13,17 +13,96 @@
package org.eclipse.jetty.server;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.Socket;
import org.eclipse.jetty.server.nio.SelectChannelConnector;
import org.eclipse.jetty.server.session.SessionHandler;
import org.eclipse.jetty.util.IO;
import org.junit.BeforeClass;
import org.junit.Test;
public class SelectChannelTimeoutTest extends ConnectorTimeoutTest
{
@BeforeClass
public static void init() throws Exception
{
SelectChannelConnector connector = new SelectChannelConnector();
connector.setMaxIdleTime(MAX_IDLE_TIME); //250 msec max idle
connector.setMaxIdleTime(MAX_IDLE_TIME); // 250 msec max idle
startServer(connector);
}
@Test
public void testIdleTimeoutAfterSuspend() throws Exception
{
SuspendHandler _handler = new SuspendHandler();
_server.stop();
SessionHandler session = new SessionHandler();
session.setHandler(_handler);
_server.setHandler(session);
_server.start();
_handler.setSuspendFor(100);
_handler.setResumeAfter(25);
assertTrue(process(null).toUpperCase().contains("DISPATCHED"));
}
@Test
public void testIdleTimeoutAfterTimeout() throws Exception
{
SuspendHandler _handler = new SuspendHandler();
_server.stop();
SessionHandler session = new SessionHandler();
session.setHandler(_handler);
_server.setHandler(session);
_server.start();
_handler.setSuspendFor(50);
assertTrue(process(null).toUpperCase().contains("TIMEOUT"));
}
@Test
public void testIdleTimeoutAfterComplete() throws Exception
{
SuspendHandler _handler = new SuspendHandler();
_server.stop();
SessionHandler session = new SessionHandler();
session.setHandler(_handler);
_server.setHandler(session);
_server.start();
_handler.setSuspendFor(100);
_handler.setCompleteAfter(25);
assertTrue(process(null).toUpperCase().contains("COMPLETED"));
}
private synchronized String process(String content) throws UnsupportedEncodingException, IOException, InterruptedException
{
String request = "GET / HTTP/1.1\r\n" + "Host: localhost\r\n" + "Connection: close\r\n";
if (content == null)
request += "\r\n";
else
request += "Content-Length: " + content.length() + "\r\n" + "\r\n" + content;
return getResponse(request);
}
private String getResponse(String request) throws UnsupportedEncodingException, IOException, InterruptedException
{
SelectChannelConnector connector = (SelectChannelConnector)_connector;
Socket socket = new Socket((String)null,connector.getLocalPort());
socket.getOutputStream().write(request.getBytes("UTF-8"));
InputStream inputStream = socket.getInputStream();
String response = IO.toString(inputStream);
Thread.sleep(500);
assertEquals("Socket should be closed and return -1 on reading",-1,socket.getInputStream().read());
return response;
}
}

View File

@ -0,0 +1,290 @@
package org.eclipse.jetty.server;
import java.io.IOException;
import java.io.InputStream;
import javax.servlet.AsyncContext;
import javax.servlet.DispatcherType;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.server.handler.HandlerWrapper;
class SuspendHandler extends HandlerWrapper
{
private int _read;
private long _suspendFor=-1;
private long _resumeAfter=-1;
private long _completeAfter=-1;
private long _suspendFor2=-1;
private long _resumeAfter2=-1;
private long _completeAfter2=-1;
public SuspendHandler()
{
}
public int getRead()
{
return _read;
}
public void setRead(int read)
{
_read = read;
}
public long getSuspendFor()
{
return _suspendFor;
}
public void setSuspendFor(long suspendFor)
{
_suspendFor = suspendFor;
}
public long getResumeAfter()
{
return _resumeAfter;
}
public void setResumeAfter(long resumeAfter)
{
_resumeAfter = resumeAfter;
}
public long getCompleteAfter()
{
return _completeAfter;
}
public void setCompleteAfter(long completeAfter)
{
_completeAfter = completeAfter;
}
/* ------------------------------------------------------------ */
/** Get the suspendFor2.
* @return the suspendFor2
*/
public long getSuspendFor2()
{
return _suspendFor2;
}
/* ------------------------------------------------------------ */
/** Set the suspendFor2.
* @param suspendFor2 the suspendFor2 to set
*/
public void setSuspendFor2(long suspendFor2)
{
_suspendFor2 = suspendFor2;
}
/* ------------------------------------------------------------ */
/** Get the resumeAfter2.
* @return the resumeAfter2
*/
public long getResumeAfter2()
{
return _resumeAfter2;
}
/* ------------------------------------------------------------ */
/** Set the resumeAfter2.
* @param resumeAfter2 the resumeAfter2 to set
*/
public void setResumeAfter2(long resumeAfter2)
{
_resumeAfter2 = resumeAfter2;
}
/* ------------------------------------------------------------ */
/** Get the completeAfter2.
* @return the completeAfter2
*/
public long getCompleteAfter2()
{
return _completeAfter2;
}
/* ------------------------------------------------------------ */
/** Set the completeAfter2.
* @param completeAfter2 the completeAfter2 to set
*/
public void setCompleteAfter2(long completeAfter2)
{
_completeAfter2 = completeAfter2;
}
@Override
public void handle(String target, final Request baseRequest, final HttpServletRequest request, final HttpServletResponse response) throws IOException, ServletException
{
try
{
if (DispatcherType.REQUEST.equals(baseRequest.getDispatcherType()))
{
if (_read>0)
{
byte[] buf=new byte[_read];
request.getInputStream().read(buf);
}
else if (_read<0)
{
InputStream in = request.getInputStream();
int b=in.read();
while(b!=-1)
b=in.read();
}
final AsyncContext asyncContext = baseRequest.startAsync();
response.getOutputStream().println("STARTASYNC");
asyncContext.addListener(LocalAsyncContextTest.__asyncListener);
asyncContext.addListener(LocalAsyncContextTest.__asyncListener1);
if (_suspendFor>0)
asyncContext.setTimeout(_suspendFor);
if (_completeAfter>0)
{
new Thread() {
@Override
public void run()
{
try
{
Thread.sleep(_completeAfter);
response.getOutputStream().println("COMPLETED");
response.setStatus(200);
baseRequest.setHandled(true);
asyncContext.complete();
}
catch(Exception e)
{
e.printStackTrace();
}
}
}.start();
}
else if (_completeAfter==0)
{
response.getOutputStream().println("COMPLETED");
response.setStatus(200);
baseRequest.setHandled(true);
asyncContext.complete();
}
if (_resumeAfter>0)
{
new Thread() {
@Override
public void run()
{
try
{
Thread.sleep(_resumeAfter);
if(((HttpServletRequest)asyncContext.getRequest()).getSession(true).getId()!=null)
asyncContext.dispatch();
}
catch(Exception e)
{
e.printStackTrace();
}
}
}.start();
}
else if (_resumeAfter==0)
{
asyncContext.dispatch();
}
}
else
{
if (request.getAttribute("TIMEOUT")!=null)
response.getOutputStream().println("TIMEOUT");
else
response.getOutputStream().println("DISPATCHED");
if (_suspendFor2>=0)
{
final AsyncContext asyncContext = baseRequest.startAsync();
response.getOutputStream().println("STARTASYNC2");
if (_suspendFor2>0)
asyncContext.setTimeout(_suspendFor2);
_suspendFor2=-1;
if (_completeAfter2>0)
{
new Thread() {
@Override
public void run()
{
try
{
Thread.sleep(_completeAfter2);
response.getOutputStream().println("COMPLETED2");
response.setStatus(200);
baseRequest.setHandled(true);
asyncContext.complete();
}
catch(Exception e)
{
e.printStackTrace();
}
}
}.start();
}
else if (_completeAfter2==0)
{
response.getOutputStream().println("COMPLETED2");
response.setStatus(200);
baseRequest.setHandled(true);
asyncContext.complete();
}
if (_resumeAfter2>0)
{
new Thread() {
@Override
public void run()
{
try
{
Thread.sleep(_resumeAfter2);
asyncContext.dispatch();
}
catch(Exception e)
{
e.printStackTrace();
}
}
}.start();
}
else if (_resumeAfter2==0)
{
asyncContext.dispatch();
}
}
else
{
response.setStatus(200);
baseRequest.setHandled(true);
}
}
}
finally
{
}
}
}

View File

@ -57,7 +57,7 @@ import org.eclipse.jetty.util.thread.QueuedThreadPool;
/**
* Asynchronous Proxy Servlet.
*
*
* Forward requests to another server either as a standard web proxy (as defined by RFC2616) or as a transparent proxy.
* <p>
* This servlet needs the jetty-util and jetty-client classes to be available to the web application.
@ -75,17 +75,15 @@ import org.eclipse.jetty.util.thread.QueuedThreadPool;
* <li>requestBufferSize - the size of the request buffer (d. 12,288)
* <li>responseHeaderSize - the size of the response header buffer (d. 6,144)
* <li>responseBufferSize - the size of the response buffer (d. 32,768)
* <li>HostHeader - Force the host header to a particular value
* <li>HostHeader - Force the host header to a particular value
* <li>whiteList - comma-separated list of allowed proxy destinations
* <li>blackList - comma-separated list of forbidden proxy destinations
* </ul>
*
*
* @see org.eclipse.jetty.server.handler.ConnectHandler
*/
public class ProxyServlet implements Servlet
{
private static final Logger LOG = Log.getLogger(ProxyServlet.class);
protected Logger _log;
protected HttpClient _client;
protected String _hostHeader;
@ -111,22 +109,22 @@ public class ProxyServlet implements Servlet
/* ------------------------------------------------------------ */
/*
* (non-Javadoc)
*
*
* @see javax.servlet.Servlet#init(javax.servlet.ServletConfig)
*/
public void init(ServletConfig config) throws ServletException
{
_config = config;
_context = config.getServletContext();
_hostHeader = config.getInitParameter("HostHeader");
try
{
_log = createLogger(config);
_log = createLogger(config);
_client = createHttpClient(config);
if (_context != null)
{
_context.setAttribute(config.getServletName() + ".Logger",_log);
@ -162,12 +160,12 @@ public class ProxyServlet implements Servlet
_log.debug(x);
}
}
/**
* Create and return a logger based on the ServletConfig for use in the
* Create and return a logger based on the ServletConfig for use in the
* proxy servlet
*
*
* @param config
* @return Logger
*/
@ -175,24 +173,24 @@ public class ProxyServlet implements Servlet
{
return Log.getLogger("org.eclipse.jetty.servlets." + config.getServletName());
}
/**
* Create and return an HttpClient based on ServletConfig
*
* By default this implementation will create an instance of the
*
* By default this implementation will create an instance of the
* HttpClient for use by this proxy servlet.
*
* @param config
* @return HttpClient
*
* @param config
* @return HttpClient
* @throws Exception
*/
protected HttpClient createHttpClient(ServletConfig config) throws Exception
{
HttpClient client = new HttpClient();
client.setConnectorType(HttpClient.CONNECTOR_SELECT_CHANNEL);
String t = config.getInitParameter("maxThreads");
if (t != null)
{
client.setThreadPool(new QueuedThreadPool(Integer.parseInt(t)));
@ -201,67 +199,67 @@ public class ProxyServlet implements Servlet
{
client.setThreadPool(new QueuedThreadPool());
}
((QueuedThreadPool)client.getThreadPool()).setName(config.getServletName());
((QueuedThreadPool)client.getThreadPool()).setName(config.getServletName());
t = config.getInitParameter("maxConnections");
if (t != null)
{
client.setMaxConnectionsPerAddress(Integer.parseInt(t));
}
t = config.getInitParameter("timeout");
if ( t != null )
{
client.setTimeout(Long.parseLong(t));
}
t = config.getInitParameter("idleTimeout");
if ( t != null )
{
client.setIdleTimeout(Long.parseLong(t));
}
t = config.getInitParameter("requestHeaderSize");
if ( t != null )
{
client.setRequestHeaderSize(Integer.parseInt(t));
}
t = config.getInitParameter("requestBufferSize");
if ( t != null )
{
client.setRequestBufferSize(Integer.parseInt(t));
}
t = config.getInitParameter("responseHeaderSize");
if ( t != null )
{
client.setResponseHeaderSize(Integer.parseInt(t));
}
t = config.getInitParameter("responseBufferSize");
if ( t != null )
{
client.setResponseBufferSize(Integer.parseInt(t));
}
client.start();
return client;
}
/* ------------------------------------------------------------ */
/**
* Helper function to process a parameter value containing a list of new entries and initialize the specified host map.
*
*
* @param list
* comma-separated list of new entries
* @param hostMap
@ -301,7 +299,7 @@ public class ProxyServlet implements Servlet
/* ------------------------------------------------------------ */
/**
* Check the request hostname and path against white- and blacklist.
*
*
* @param host
* hostname to check
* @param path
@ -353,7 +351,7 @@ public class ProxyServlet implements Servlet
/* ------------------------------------------------------------ */
/*
* (non-Javadoc)
*
*
* @see javax.servlet.Servlet#getServletConfig()
*/
public ServletConfig getServletConfig()
@ -364,7 +362,7 @@ public class ProxyServlet implements Servlet
/* ------------------------------------------------------------ */
/**
* Get the hostHeader.
*
*
* @return the hostHeader
*/
public String getHostHeader()
@ -375,7 +373,7 @@ public class ProxyServlet implements Servlet
/* ------------------------------------------------------------ */
/**
* Set the hostHeader.
*
*
* @param hostHeader
* the hostHeader to set
*/
@ -387,7 +385,7 @@ public class ProxyServlet implements Servlet
/* ------------------------------------------------------------ */
/*
* (non-Javadoc)
*
*
* @see javax.servlet.Servlet#service(javax.servlet.ServletRequest, javax.servlet.ServletResponse)
*/
public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException
@ -412,7 +410,7 @@ public class ProxyServlet implements Servlet
response.sendError(HttpServletResponse.SC_GATEWAY_TIMEOUT); // Need better test that isInitial
else
{
String uri = request.getRequestURI();
if (request.getQueryString() != null)
uri += "?" + request.getQueryString();
@ -430,14 +428,17 @@ public class ProxyServlet implements Servlet
HttpExchange exchange = new HttpExchange()
{
@Override
protected void onRequestCommitted() throws IOException
{
}
@Override
protected void onRequestComplete() throws IOException
{
}
@Override
protected void onResponseComplete() throws IOException
{
if (debug != 0)
@ -445,6 +446,7 @@ public class ProxyServlet implements Servlet
continuation.complete();
}
@Override
protected void onResponseContent(Buffer content) throws IOException
{
if (debug != 0)
@ -452,10 +454,12 @@ public class ProxyServlet implements Servlet
content.writeTo(out);
}
@Override
protected void onResponseHeaderComplete() throws IOException
{
}
@Override
protected void onResponseStatus(Buffer version, int status, Buffer reason) throws IOException
{
if (debug != 0)
@ -467,6 +471,7 @@ public class ProxyServlet implements Servlet
response.setStatus(status);
}
@Override
protected void onResponseHeader(Buffer name, Buffer value) throws IOException
{
String s = name.toString().toLowerCase();
@ -481,11 +486,12 @@ public class ProxyServlet implements Servlet
_log.debug(debug + " " + name + "! " + value);
}
@Override
protected void onConnectionFailed(Throwable ex)
{
handleOnConnectionFailed(ex,request,response);
// it is possible this might trigger before the
// it is possible this might trigger before the
// continuation.suspend()
if (!continuation.isInitial())
{
@ -493,16 +499,17 @@ public class ProxyServlet implements Servlet
}
}
@Override
protected void onException(Throwable ex)
{
if (ex instanceof EofException)
{
LOG.ignore(ex);
_log.ignore(ex);
return;
}
handleOnException(ex,request,response);
// it is possible this might trigger before the
// it is possible this might trigger before the
// continuation.suspend()
if (!continuation.isInitial())
{
@ -510,6 +517,7 @@ public class ProxyServlet implements Servlet
}
}
@Override
protected void onExpire()
{
handleOnExpire(request,response);
@ -597,14 +605,14 @@ public class ProxyServlet implements Servlet
if (hasContent)
exchange.setRequestContentSource(in);
customizeExchange(exchange, request);
customizeExchange(exchange, request);
/*
* we need to set the timeout on the continuation to take into
* account the timeout of the HttpClient and the HttpExchange
*/
long ctimeout = (_client.getTimeout() > exchange.getTimeout()) ? _client.getTimeout() : exchange.getTimeout();
// continuation fudge factor of 1000, underlying components
// should fail/expire first from exchange
if ( ctimeout == 0 )
@ -612,12 +620,12 @@ public class ProxyServlet implements Servlet
continuation.setTimeout(0); // ideally never times out
}
else
{
{
continuation.setTimeout(ctimeout + 1000);
}
customizeContinuation(continuation);
continuation.suspend(response);
_client.send(exchange);
@ -678,7 +686,7 @@ public class ProxyServlet implements Servlet
/*
* (non-Javadoc)
*
*
* @see javax.servlet.Servlet#getServletInfo()
*/
public String getServletInfo()
@ -689,7 +697,7 @@ public class ProxyServlet implements Servlet
/**
* Extension point for subclasses to customize an exchange. Useful for setting timeouts etc. The default implementation does nothing.
*
*
* @param exchange
* @param request
*/
@ -701,7 +709,7 @@ public class ProxyServlet implements Servlet
/**
* Extension point for subclasses to customize the Continuation after it's initial creation in the service method. Useful for setting timeouts etc. The
* default implementation does nothing.
*
*
* @param continuation
*/
protected void customizeContinuation(Continuation continuation)
@ -712,7 +720,7 @@ public class ProxyServlet implements Servlet
/**
* Extension point for custom handling of an HttpExchange's onConnectionFailed method. The default implementation delegates to
* {@link #handleOnException(Throwable, javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)}
*
*
* @param ex
* @param request
* @param response
@ -725,15 +733,15 @@ public class ProxyServlet implements Servlet
/**
* Extension point for custom handling of an HttpExchange's onException method. The default implementation sets the response status to
* HttpServletResponse.SC_INTERNAL_SERVER_ERROR (503)
*
*
* @param ex
* @param request
* @param response
*/
protected void handleOnException(Throwable ex, HttpServletRequest request, HttpServletResponse response)
{
LOG.warn(ex.toString());
LOG.debug(ex);
_log.warn(ex.toString());
_log.debug(ex);
if (!response.isCommitted())
{
response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
@ -743,7 +751,7 @@ public class ProxyServlet implements Servlet
/**
* Extension point for custom handling of an HttpExchange's onExpire method. The default implementation sets the response status to
* HttpServletResponse.SC_GATEWAY_TIMEOUT (504)
*
*
* @param request
* @param response
*/
@ -757,7 +765,7 @@ public class ProxyServlet implements Servlet
/**
* Transparent Proxy.
*
*
* This convenience extension to ProxyServlet configures the servlet as a transparent proxy. The servlet is configured with init parameters:
* <ul>
* <li>ProxyTo - a URI like http://host:80/context to which the request is proxied.
@ -765,7 +773,7 @@ public class ProxyServlet implements Servlet
* </ul>
* For example, if a request was received at /foo/bar and the ProxyTo was http://host:80/context and the Prefix was /foo, then the request would be proxied
* to http://host:80/context/bar
*
*
*/
public static class Transparent extends ProxyServlet
{

View File

@ -123,30 +123,35 @@ public class Main
// if no non-option inis, add the start.ini and start.d
if (!ini)
{
List<String> ini_args=new ArrayList<String>();
File start_ini = new File(_jettyHome,"start.ini");
if (start_ini.exists())
ini_args.addAll(loadStartIni(start_ini));
File start_d = new File(_jettyHome,"start.d");
if (start_d.isDirectory())
{
File[] inis = start_d.listFiles(new FilenameFilter()
{
public boolean accept(File dir, String name)
{
return name.toLowerCase().endsWith(".ini");
}
});
Arrays.sort(inis);
for (File i : inis)
ini_args.addAll(loadStartIni(i));
}
arguments.addAll(0,ini_args);
arguments.addAll(0,parseStartIniFiles());
}
return arguments;
}
List<String> parseStartIniFiles()
{
List<String> ini_args=new ArrayList<String>();
File start_ini = new File(_jettyHome,"start.ini");
if (start_ini.exists())
ini_args.addAll(loadStartIni(start_ini));
File start_d = new File(_jettyHome,"start.d");
if (start_d.isDirectory())
{
File[] inis = start_d.listFiles(new FilenameFilter()
{
public boolean accept(File dir, String name)
{
return name.toLowerCase().endsWith(".ini");
}
});
Arrays.sort(inis);
for (File i : inis)
ini_args.addAll(loadStartIni(i));
}
return ini_args;
}
public List<String> processCommandLine(List<String> arguments) throws Exception
{
@ -1075,7 +1080,7 @@ public class Main
}
catch (IOException e)
{
// usageExit(e,ERR_UNKNOWN);
usageExit(e,ERR_UNKNOWN);
}
finally
{

View File

@ -20,7 +20,7 @@ Command Line Options:
when the start.ini includes -X or -D arguments.
--exec Run the generated command line (see --dry-run) in
a sub processes. This can be used when start.ini
a sub process. This can be used when start.ini
contains -X or -D arguments, but creates an extra
JVM instance.
@ -36,8 +36,10 @@ Command Line Options:
--ini=<file> Load command line arguments from a file. If
no --ini options are specified, then the
start.ini file will be read if it exists.
A --ini option with no file indicates that
start.ini file will be read if it exists in
jetty.home. If specified jetty.home/start.ini
and additional .ini files in jetty.home/start.d/
will NOT be read. A --ini option with no file indicates that
start.ini should not be read.
--pre=<file> Specify a configuration file that is to be processed
@ -116,10 +118,10 @@ Available Configurations:
Defaults:
A start.ini file may be used to specify default arguments to start.jar,
which are used if no command line arguments are provided and override
the defaults in the start.config file. If the directory start.d exists,
then multiple *.ini files will be read from that directory in alphabetical
order. If --ini options are provided on the command line, then start.ini
and start.d will not be read.
the defaults in the start.config file. If the directory jetty.home/start.d
exists, then multiple *.ini files will be read from that directory in
alphabetical order. If --ini options are provided on the command line,
then start.ini and start.d will NOT be read.
The current start.ini arguments are:

View File

@ -15,7 +15,7 @@ package org.eclipse.jetty.start;
import static org.junit.Assert.assertEquals;
import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.util.List;
@ -39,15 +39,18 @@ public class MainTest
/**
* Test method for {@link org.eclipse.jetty.start.StartIniParser#loadStartIni(java.lang.String)}.
* @throws IOException
*/
@Test
public void testLoadStartIni()
public void testLoadStartIni() throws IOException
{
URL startIni = this.getClass().getResource("/jetty.home/start.ini");
String startIniFileName = startIni.getFile();
List<String> args = Main.loadStartIni(new File(startIniFileName));
assertEquals("Expected 5 uncommented lines in start.ini",5,args.size());
URL startIni = this.getClass().getResource("/jetty.home/");
System.setProperty("jetty.home",startIni.getFile());
Main main = new Main();
List<String> args = main.parseStartIniFiles();
assertEquals("Expected 5 uncommented lines in start.ini",9,args.size());
assertEquals("First uncommented line in start.ini doesn't match expected result","OPTIONS=Server,jsp,resources,websocket,ext",args.get(0));
assertEquals("Last uncommented line in start.ini doesn't match expected result","etc/jetty-testrealm.xml",args.get(8));
}
@Test

View File

@ -102,7 +102,10 @@ public class Log
while (systemKeyEnum.hasMoreElements())
{
String key = systemKeyEnum.nextElement();
__props.setProperty(key,System.getProperty(key));
String val = System.getProperty(key);
//protect against application code insertion of non-String values (returned as null)
if (val != null)
__props.setProperty(key,val);
}
/* Now use the configuration properties to configure the Log statics

View File

@ -45,6 +45,7 @@ import org.eclipse.jetty.io.nio.SslConnection;
import org.eclipse.jetty.util.B64Code;
import org.eclipse.jetty.util.QuotedStringTokenizer;
import org.eclipse.jetty.util.component.AggregateLifeCycle;
import org.eclipse.jetty.util.component.LifeCycle;
import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.util.ssl.SslContextFactory;
import org.eclipse.jetty.util.thread.QueuedThreadPool;
@ -67,6 +68,7 @@ public class WebSocketClientFactory extends AggregateLifeCycle
private final Queue<WebSocketConnection> connections = new ConcurrentLinkedQueue<WebSocketConnection>();
private final SslContextFactory _sslContextFactory = new SslContextFactory();
private final ThreadPool _threadPool;
private final boolean _shutdownThreadPool;
private final WebSocketClientSelector _selector;
private MaskGen _maskGen;
private WebSocketBuffers _buffers;
@ -77,7 +79,7 @@ public class WebSocketClientFactory extends AggregateLifeCycle
*/
public WebSocketClientFactory()
{
this(new QueuedThreadPool());
this(null);
}
/* ------------------------------------------------------------ */
@ -114,14 +116,27 @@ public class WebSocketClientFactory extends AggregateLifeCycle
*/
public WebSocketClientFactory(ThreadPool threadPool, MaskGen maskGen, int bufferSize)
{
_threadPool = threadPool;
addBean(threadPool);
if (threadPool == null)
{
_threadPool = new QueuedThreadPool();
addBean(_threadPool);
_shutdownThreadPool = true;
}
else
{
_threadPool = threadPool;
_shutdownThreadPool = false;
}
_buffers = new WebSocketBuffers(bufferSize);
addBean(_buffers);
_maskGen = maskGen;
addBean(_maskGen);
_selector = new WebSocketClientSelector();
addBean(_selector);
addBean(_sslContextFactory);
}
@ -208,6 +223,9 @@ public class WebSocketClientFactory extends AggregateLifeCycle
protected void doStop() throws Exception
{
closeConnections();
super.doStop();
if (_shutdownThreadPool && _threadPool instanceof LifeCycle)
((LifeCycle)_threadPool).stop();
}
/* ------------------------------------------------------------ */

View File

@ -121,7 +121,7 @@ public class WebSocketConnectionRFC6455 extends AbstractConnection implements We
private final static byte[] MAGIC;
private final List<Extension> _extensions;
private final WebSocketParserD13 _parser;
private final WebSocketParserRFC6455 _parser;
private final WebSocketGeneratorRFC6455 _generator;
private final WebSocketGenerator _outbound;
private final WebSocket _webSocket;
@ -197,7 +197,7 @@ public class WebSocketConnectionRFC6455 extends AbstractConnection implements We
_outbound=(_extensions==null||_extensions.size()==0)?_generator:extensions.get(extensions.size()-1);
WebSocketParser.FrameHandler inbound = (_extensions == null || _extensions.size() == 0) ? frameHandler : extensions.get(0);
_parser = new WebSocketParserD13(buffers, endpoint, inbound,maskgen==null);
_parser = new WebSocketParserRFC6455(buffers, endpoint, inbound,maskgen==null);
_protocol=protocol;
@ -642,7 +642,13 @@ public class WebSocketConnectionRFC6455 extends AbstractConnection implements We
@Override
public String toString()
{
return this.getClass().getSimpleName()+"D13@"+_endp.getLocalAddr()+":"+_endp.getLocalPort()+"<->"+_endp.getRemoteAddr()+":"+_endp.getRemotePort();
return String.format("%s@%x l(%s:%d)<->r(%s:%d)",
getClass().getSimpleName(),
hashCode(),
_endp.getLocalAddr(),
_endp.getLocalPort(),
_endp.getRemoteAddr(),
_endp.getRemotePort());
}
}
@ -973,6 +979,6 @@ public class WebSocketConnectionRFC6455 extends AbstractConnection implements We
@Override
public String toString()
{
return String.format("WS/D%d p=%s g=%s", _draft, _parser, _generator);
return String.format("%s p=%s g=%s", getClass().getSimpleName(), _parser, _generator);
}
}

View File

@ -43,9 +43,9 @@ import org.eclipse.jetty.util.log.Logger;
* Parser the WebSocket protocol.
*
*/
public class WebSocketParserD13 implements WebSocketParser
public class WebSocketParserRFC6455 implements WebSocketParser
{
private static final Logger LOG = Log.getLogger(WebSocketParserD13.class);
private static final Logger LOG = Log.getLogger(WebSocketParserRFC6455.class);
public enum State {
@ -89,7 +89,7 @@ public class WebSocketParserD13 implements WebSocketParser
* @param handler the handler to notify when a parse event occurs
* @param shouldBeMasked whether masking should be handled
*/
public WebSocketParserD13(WebSocketBuffers buffers, EndPoint endp, FrameHandler handler, boolean shouldBeMasked)
public WebSocketParserRFC6455(WebSocketBuffers buffers, EndPoint endp, FrameHandler handler, boolean shouldBeMasked)
{
_buffers=buffers;
_endp=endp;

View File

@ -15,8 +15,6 @@
*******************************************************************************/
package org.eclipse.jetty.websocket;
import static org.hamcrest.Matchers.*;
import java.net.URI;
import java.util.concurrent.TimeUnit;
@ -24,7 +22,6 @@ import org.eclipse.jetty.server.Connector;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.servlet.ServletHolder;
import org.eclipse.jetty.util.log.StdErrLog;
import org.eclipse.jetty.websocket.helper.CaptureSocket;
import org.eclipse.jetty.websocket.helper.SafariD00;
import org.eclipse.jetty.websocket.helper.WebSocketCaptureServlet;
@ -32,9 +29,11 @@ import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Ignore;
import org.junit.Test;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.notNullValue;
public class SafariWebsocketDraft0Test
{
private Server server;
@ -76,7 +75,7 @@ public class SafariWebsocketDraft0Test
serverUri = new URI(String.format("ws://%s:%d/",host,port));
// System.out.printf("Server URI: %s%n",serverUri);
}
@Test
public void testSendTextMessages() throws Exception
{
@ -96,10 +95,11 @@ public class SafariWebsocketDraft0Test
CaptureSocket socket = servlet.captures.get(0);
Assert.assertThat("CaptureSocket",socket,notNullValue());
Assert.assertThat("CaptureSocket.isConnected", socket.isConnected(), is(true));
Assert.assertThat("CaptureSocket.isConnected", socket.awaitConnected(1000), is(true));
// Give servlet 500 millisecond to process messages
// Give servlet time to process messages
threadSleep(1,TimeUnit.SECONDS);
// Should have captured 5 messages.
Assert.assertThat("CaptureSocket.messages.size",socket.messages.size(),is(5));
}
@ -109,13 +109,13 @@ public class SafariWebsocketDraft0Test
safari.disconnect();
}
}
public static void threadSleep(int dur, TimeUnit unit) throws InterruptedException
{
long ms = TimeUnit.MILLISECONDS.convert(dur,unit);
Thread.sleep(ms);
}
@After
public void stopServer() throws Exception
{

View File

@ -74,8 +74,10 @@ public class WebSocketClientTest
@Test
public void testMessageBiggerThanBufferSize() throws Exception
{
QueuedThreadPool threadPool = new QueuedThreadPool();
int bufferSize = 512;
WebSocketClientFactory factory = new WebSocketClientFactory(new QueuedThreadPool(), new ZeroMaskGen(), bufferSize);
WebSocketClientFactory factory = new WebSocketClientFactory(threadPool, new ZeroMaskGen(), bufferSize);
threadPool.start();
factory.start();
WebSocketClient client = new WebSocketClient(factory);
@ -118,6 +120,7 @@ public class WebSocketClientTest
Assert.assertTrue(dataLatch.await(1000, TimeUnit.SECONDS));
factory.stop();
threadPool.stop();
}
@Test

View File

@ -15,8 +15,6 @@
*******************************************************************************/
package org.eclipse.jetty.websocket;
import static org.hamcrest.Matchers.*;
import java.net.URI;
import java.util.concurrent.TimeUnit;
@ -32,6 +30,9 @@ import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.notNullValue;
/**
* WebSocketCommTest - to test reported undelivered messages in bug <a
* href="https://jira.codehaus.org/browse/JETTY-1463">JETTY-1463</a>
@ -109,11 +110,11 @@ public class WebSocketCommTest
CaptureSocket socket = servlet.captures.get(0);
Assert.assertThat("CaptureSocket",socket,notNullValue());
Assert.assertThat("CaptureSocket.isConnected",socket.isConnected(),is(true));
Assert.assertThat("CaptureSocket.isConnected",socket.awaitConnected(1000),is(true));
// Give servlet 500 millisecond to process messages
// Give servlet time to process messages
TimeUnit.MILLISECONDS.sleep(500);
// Should have captured 5 messages.
Assert.assertThat("CaptureSocket.messages.size",socket.messages.size(),is(5));
}

View File

@ -15,8 +15,6 @@
*******************************************************************************/
package org.eclipse.jetty.websocket;
import static org.junit.Assert.*;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
@ -28,11 +26,9 @@ import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import javax.servlet.http.HttpServletRequest;
import junit.framework.Assert;
import org.eclipse.jetty.io.Buffer;
import org.eclipse.jetty.io.bio.SocketEndPoint;
import org.eclipse.jetty.server.Connector;
@ -45,7 +41,9 @@ import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
public class WebSocketLoadD13Test
import static org.junit.Assert.assertTrue;
public class WebSocketLoadRFC6455Test
{
private static Server _server;
private static Connector _connector;
@ -127,7 +125,7 @@ public class WebSocketLoadD13Test
{
this.outbound = outbound;
}
public void onMessage(String data)
{
try
@ -155,7 +153,7 @@ public class WebSocketLoadD13Test
private final CountDownLatch latch;
private final SocketEndPoint _endp;
private final WebSocketGeneratorRFC6455 _generator;
private final WebSocketParserD13 _parser;
private final WebSocketParserRFC6455 _parser;
private final WebSocketParser.FrameHandler _handler = new WebSocketParser.FrameHandler()
{
public void onFrame(byte flags, byte opcode, Buffer buffer)
@ -168,7 +166,7 @@ public class WebSocketLoadD13Test
}
};
private volatile Buffer _response;
public WebSocketClient(String host, int port, int readTimeout, CountDownLatch latch, int iterations) throws IOException
{
this.latch = latch;
@ -177,11 +175,11 @@ public class WebSocketLoadD13Test
output = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream(), "ISO-8859-1"));
input = new BufferedReader(new InputStreamReader(socket.getInputStream(), "ISO-8859-1"));
this.iterations = iterations;
_endp=new SocketEndPoint(socket);
_generator = new WebSocketGeneratorRFC6455(new WebSocketBuffers(32*1024),_endp,new FixedMaskGen());
_parser = new WebSocketParserD13(new WebSocketBuffers(32*1024),_endp,_handler,false);
_parser = new WebSocketParserRFC6455(new WebSocketBuffers(32*1024),_endp,_handler,false);
}
private void open() throws IOException
@ -216,9 +214,9 @@ public class WebSocketLoadD13Test
byte[] data = message.getBytes(StringUtil.__UTF8);
_generator.addFrame((byte)0x8,WebSocketConnectionRFC6455.OP_TEXT,data,0,data.length);
_generator.flush();
//System.err.println("-> "+message);
_response=null;
while(_response==null)
_parser.parseNext();

View File

@ -15,8 +15,6 @@
*******************************************************************************/
package org.eclipse.jetty.websocket;
import static org.junit.Assert.*;
import java.io.EOFException;
import java.io.IOException;
import java.io.InputStream;
@ -30,11 +28,9 @@ import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.atomic.AtomicReference;
import java.util.zip.Deflater;
import java.util.zip.Inflater;
import javax.servlet.http.HttpServletRequest;
import junit.framework.Assert;
import org.eclipse.jetty.io.Buffer;
import org.eclipse.jetty.io.ByteArrayEndPoint;
import org.eclipse.jetty.server.Connector;
@ -48,6 +44,10 @@ import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
public class WebSocketMessageRFC6455Test
{
private static Server __server;
@ -78,7 +78,7 @@ public class WebSocketMessageRFC6455Test
}
};
wsHandler.getWebSocketFactory().setBufferSize(8192);
wsHandler.getWebSocketFactory().setMaxIdleTime(1000);
wsHandler.getWebSocketFactory().setMaxIdleTime(1000);
wsHandler.setHandler(new DefaultHandler());
__server.setHandler(wsHandler);
__server.start();
@ -91,13 +91,13 @@ public class WebSocketMessageRFC6455Test
__server.join();
}
@Test
public void testHash()
{
assertEquals("s3pPLMBiTxaQ9kYGzzhZRbK+xOo=",WebSocketConnectionRFC6455.hashKey("dGhlIHNhbXBsZSBub25jZQ=="));
}
@Test
public void testServerSendBigStringMessage() throws Exception
{
@ -119,7 +119,7 @@ public class WebSocketMessageRFC6455Test
socket.setSoTimeout(1000);
InputStream input = socket.getInputStream();
lookFor("HTTP/1.1 101 Switching Protocols\r\n",input);
skipTo("Sec-WebSocket-Accept: ",input);
lookFor("s3pPLMBiTxaQ9kYGzzhZRbK+xOo=",input);
@ -127,7 +127,7 @@ public class WebSocketMessageRFC6455Test
assertTrue(__serverWebSocket.awaitConnected(1000));
assertNotNull(__serverWebSocket.connection);
// Server sends a big message
StringBuilder message = new StringBuilder();
String text = "0123456789ABCDEF";
@ -167,7 +167,7 @@ public class WebSocketMessageRFC6455Test
socket.setSoTimeout(1000);
InputStream input = socket.getInputStream();
lookFor("HTTP/1.1 101 Switching Protocols\r\n",input);
skipTo("Sec-WebSocket-Accept: ",input);
lookFor("s3pPLMBiTxaQ9kYGzzhZRbK+xOo=",input);
@ -175,7 +175,7 @@ public class WebSocketMessageRFC6455Test
assertTrue(__serverWebSocket.awaitConnected(1000));
assertNotNull(__serverWebSocket.connection);
assertEquals(0x81,input.read());
assertEquals(0x0f,input.read());
lookFor("sent on connect",input);
@ -312,8 +312,8 @@ public class WebSocketMessageRFC6455Test
assertTrue(__serverWebSocket.awaitConnected(1000));
assertNotNull(__serverWebSocket.connection);
// Server sends a big message
String text = "0123456789ABCDEF ";
text=text+text+text+text;
@ -324,15 +324,15 @@ public class WebSocketMessageRFC6455Test
deflater.setInput(data);
deflater.finish();
byte[] buf=new byte[data.length];
buf[0]=(byte)((byte)0x7e);
buf[1]=(byte)(data.length>>8);
buf[2]=(byte)(data.length&0xff);
int l=deflater.deflate(buf,3,buf.length-3);
assertTrue(deflater.finished());
output.write(0xC1);
output.write((byte)(0x80|(0xff&(l+3))));
output.write(0x00);
@ -341,41 +341,41 @@ public class WebSocketMessageRFC6455Test
output.write(0x00);
output.write(buf,0,l+3);
output.flush();
assertEquals(0x40+WebSocketConnectionRFC6455.OP_TEXT,input.read());
assertEquals(0x20+3,input.read());
assertEquals(0x7e,input.read());
assertEquals(0x02,input.read());
assertEquals(0x20,input.read());
byte[] raw = new byte[32];
assertEquals(32,input.read(raw));
Inflater inflater = new Inflater();
inflater.setInput(raw);
byte[] result = new byte[544];
assertEquals(544,inflater.inflate(result));
assertEquals(TypeUtil.toHexString(data,0,544),TypeUtil.toHexString(result));
assertEquals((byte)0xC0,(byte)input.read());
assertEquals(0x21+3,input.read());
assertEquals(0x7e,input.read());
assertEquals(0x02,input.read());
assertEquals(0x21,input.read());
assertEquals(32,input.read(raw));
inflater.reset();
inflater.setInput(raw);
result = new byte[545];
assertEquals(545,inflater.inflate(result));
assertEquals(TypeUtil.toHexString(data,544,545),TypeUtil.toHexString(result));
}
@Test
public void testServerEcho() throws Exception
{
@ -403,10 +403,10 @@ public class WebSocketMessageRFC6455Test
output.write(bytes[i]^0xff);
output.flush();
// Make sure the read times out if there are problems with the implementation
socket.setSoTimeout(1000);
socket.setSoTimeout(1000);
InputStream input = socket.getInputStream();
lookFor("HTTP/1.1 101 Switching Protocols\r\n",input);
skipTo("Sec-WebSocket-Accept: ",input);
lookFor("s3pPLMBiTxaQ9kYGzzhZRbK+xOo=",input);
@ -414,12 +414,12 @@ public class WebSocketMessageRFC6455Test
assertTrue(__serverWebSocket.awaitConnected(1000));
assertNotNull(__serverWebSocket.connection);
assertEquals(0x84,input.read());
assertEquals(0x0f,input.read());
lookFor("this is an echo",input);
}
@Test
public void testBlockedConsumer() throws Exception
{
@ -436,7 +436,7 @@ public class WebSocketMessageRFC6455Test
mesg[5]=(byte)0xff;
for (int i=0;i<bytes.length;i++)
mesg[6+i]=(byte)(bytes[i]^0xff);
final int count = 100000;
output.write(
@ -489,7 +489,7 @@ public class WebSocketMessageRFC6455Test
}
}
}.start();
// Send enough messages to fill receive buffer
long max=0;
long start=System.currentTimeMillis();
@ -500,7 +500,7 @@ public class WebSocketMessageRFC6455Test
{
// System.err.println(">>> "+i);
output.flush();
long now=System.currentTimeMillis();
long duration=now-start;
start=now;
@ -518,13 +518,13 @@ public class WebSocketMessageRFC6455Test
assertEquals(count+1,__textCount.get()); // all messages
assertTrue(max>2000); // was blocked
}
@Test
public void testBlockedProducer() throws Exception
{
final Socket socket = new Socket("localhost", __connector.getLocalPort());
OutputStream output = socket.getOutputStream();
final int count = 100000;
output.write(
@ -581,8 +581,8 @@ public class WebSocketMessageRFC6455Test
}
}
}.start();
// Send enough messages to fill receive buffer
long max=0;
long start=System.currentTimeMillis();
@ -593,7 +593,7 @@ public class WebSocketMessageRFC6455Test
if (i%100==0)
{
output.flush();
long now=System.currentTimeMillis();
long duration=now-start;
start=now;
@ -601,10 +601,10 @@ public class WebSocketMessageRFC6455Test
max=duration;
}
}
while(totalB.get()<(count*(mesg.length()+2)))
Thread.sleep(100);
assertEquals(count*(mesg.length()+2),totalB.get()); // all messages
assertTrue(max>1000); // was blocked
}
@ -635,7 +635,7 @@ public class WebSocketMessageRFC6455Test
output.flush();
InputStream input = socket.getInputStream();
lookFor("HTTP/1.1 101 Switching Protocols\r\n",input);
skipTo("Sec-WebSocket-Accept: ",input);
lookFor("s3pPLMBiTxaQ9kYGzzhZRbK+xOo=",input);
@ -668,7 +668,7 @@ public class WebSocketMessageRFC6455Test
socket.setSoTimeout(1000);
InputStream input = socket.getInputStream();
lookFor("HTTP/1.1 101 Switching Protocols\r\n",input);
skipTo("Sec-WebSocket-Accept: ",input);
lookFor("s3pPLMBiTxaQ9kYGzzhZRbK+xOo=",input);
@ -676,10 +676,10 @@ public class WebSocketMessageRFC6455Test
assertTrue(__serverWebSocket.awaitConnected(1000));
assertNotNull(__serverWebSocket.connection);
__serverWebSocket.getConnection().setMaxTextMessageSize(10*1024);
__serverWebSocket.getConnection().setAllowFrameFragmentation(true);
output.write(0x81);
output.write(0x80|0x7E);
output.write((byte)((16*1024)>>8));
@ -692,7 +692,7 @@ public class WebSocketMessageRFC6455Test
for (int i=0;i<(16*1024);i++)
output.write('X');
output.flush();
assertEquals(0x80|WebSocketConnectionRFC6455.OP_CLOSE,input.read());
assertEquals(33,input.read());
@ -720,7 +720,7 @@ public class WebSocketMessageRFC6455Test
socket.setSoTimeout(1000);
InputStream input = socket.getInputStream();
lookFor("HTTP/1.1 101 Switching Protocols\r\n",input);
skipTo("Sec-WebSocket-Accept: ",input);
lookFor("s3pPLMBiTxaQ9kYGzzhZRbK+xOo=",input);
@ -728,9 +728,9 @@ public class WebSocketMessageRFC6455Test
assertTrue(__serverWebSocket.awaitConnected(1000));
assertNotNull(__serverWebSocket.connection);
__serverWebSocket.getConnection().setMaxTextMessageSize(15);
output.write(0x01);
output.write(0x8a);
output.write(0xff);
@ -779,7 +779,7 @@ public class WebSocketMessageRFC6455Test
socket.setSoTimeout(100000);
InputStream input = socket.getInputStream();
lookFor("HTTP/1.1 101 Switching Protocols\r\n",input);
skipTo("Sec-WebSocket-Accept: ",input);
lookFor("s3pPLMBiTxaQ9kYGzzhZRbK+xOo=",input);
@ -787,9 +787,9 @@ public class WebSocketMessageRFC6455Test
assertTrue(__serverWebSocket.awaitConnected(1000));
assertNotNull(__serverWebSocket.connection);
__serverWebSocket.getConnection().setMaxTextMessageSize(15);
output.write(0x01);
output.write(0x94);
output.write(0xff);
@ -800,9 +800,9 @@ public class WebSocketMessageRFC6455Test
for (int i=0;i<bytes.length;i++)
output.write(bytes[i]^0xff);
output.flush();
assertEquals(0x80|WebSocketConnectionRFC6455.OP_CLOSE,input.read());
assertEquals(30,input.read());
int code=(0xff&input.read())*0x100+(0xff&input.read());
@ -829,7 +829,7 @@ public class WebSocketMessageRFC6455Test
socket.setSoTimeout(1000);
InputStream input = socket.getInputStream();
lookFor("HTTP/1.1 101 Switching Protocols\r\n",input);
skipTo("Sec-WebSocket-Accept: ",input);
lookFor("s3pPLMBiTxaQ9kYGzzhZRbK+xOo=",input);
@ -838,7 +838,7 @@ public class WebSocketMessageRFC6455Test
assertTrue(__serverWebSocket.awaitConnected(1000));
assertNotNull(__serverWebSocket.connection);
__serverWebSocket.getConnection().setMaxBinaryMessageSize(1024);
output.write(WebSocketConnectionRFC6455.OP_BINARY);
output.write(0x8a);
output.write(0xff);
@ -859,12 +859,12 @@ public class WebSocketMessageRFC6455Test
for (int i=0;i<bytes.length;i++)
output.write(bytes[i]^0xff);
output.flush();
assertEquals(0x80+WebSocketConnectionRFC6455.OP_BINARY,input.read());
assertEquals(20,input.read());
lookFor("01234567890123456789",input);
}
@Test
public void testMaxBinarySize() throws Exception
{
@ -884,7 +884,7 @@ public class WebSocketMessageRFC6455Test
socket.setSoTimeout(100000);
InputStream input = socket.getInputStream();
lookFor("HTTP/1.1 101 Switching Protocols\r\n",input);
skipTo("Sec-WebSocket-Accept: ",input);
lookFor("s3pPLMBiTxaQ9kYGzzhZRbK+xOo=",input);
@ -892,9 +892,9 @@ public class WebSocketMessageRFC6455Test
assertTrue(__serverWebSocket.awaitConnected(1000));
assertNotNull(__serverWebSocket.connection);
__serverWebSocket.getConnection().setMaxBinaryMessageSize(15);
output.write(0x02);
output.write(0x8a);
output.write(0xff);
@ -916,20 +916,20 @@ public class WebSocketMessageRFC6455Test
output.write(bytes[i]^0xff);
output.flush();
assertEquals(0x80|WebSocketConnectionRFC6455.OP_CLOSE,input.read());
assertEquals(19,input.read());
int code=(0xff&input.read())*0x100+(0xff&input.read());
assertEquals(WebSocketConnectionRFC6455.CLOSE_MESSAGE_TOO_LARGE,code);
lookFor("Message size > 15",input);
}
@Test
public void testCloseIn() throws Exception
{
int[][] tests =
int[][] tests =
{
{-1,0,-1},
{-1,0,-1},
@ -960,7 +960,7 @@ public class WebSocketMessageRFC6455Test
"",
"mesg"
};
String[] resp =
{
"",
@ -1007,14 +1007,14 @@ public class WebSocketMessageRFC6455Test
int code=tests[t][0];
String m=mesg[t];
output.write(0x88);
output.write(0x80 + (code<=0?0:(2+m.length())));
output.write(0x00);
output.write(0x00);
output.write(0x00);
output.write(0x00);
if (code>0)
{
output.write(code/0x100);
@ -1022,12 +1022,12 @@ public class WebSocketMessageRFC6455Test
output.write(m.getBytes());
}
output.flush();
__serverWebSocket.awaitDisconnected(1000);
byte[] buf = new byte[128];
int len = input.read(buf);
assertEquals(tst,2+tests[t][1],len);
assertEquals(tst,(byte)0x88,buf[0]);
@ -1035,7 +1035,7 @@ public class WebSocketMessageRFC6455Test
{
code=(0xff&buf[2])*0x100+(0xff&buf[3]);
assertEquals(tst,tests[t][2],code);
if (len>4)
{
m = new String(buf,4,len-4,"UTF-8");
@ -1044,19 +1044,19 @@ public class WebSocketMessageRFC6455Test
}
else
assertEquals(tst,tests[t][2],-1);
len = input.read(buf);
assertEquals(tst,-1,len);
}
}
@Test
public void testCloseOut() throws Exception
{
int[][] tests =
int[][] tests =
{
{-1,0,-1},
{-1,0,-1},
@ -1127,7 +1127,7 @@ public class WebSocketMessageRFC6455Test
{
int code=(0xff&buf[2])*0x100+(0xff&buf[3]);
assertEquals(tst,tests[t][2],code);
if (len>4)
{
String m = new String(buf,4,len-4,"UTF-8");
@ -1136,7 +1136,7 @@ public class WebSocketMessageRFC6455Test
}
else
assertEquals(tst,tests[t][2],-1);
try
{
output.write(0x88);
@ -1152,12 +1152,12 @@ public class WebSocketMessageRFC6455Test
System.err.println("socket "+socket);
throw e;
}
len = input.read(buf);
assertEquals(tst,-1,len);
}
}
}
@Test
public void testNotUTF8() throws Exception
@ -1225,7 +1225,7 @@ public class WebSocketMessageRFC6455Test
socket.setSoTimeout(100000);
InputStream input = socket.getInputStream();
lookFor("HTTP/1.1 101 Switching Protocols\r\n",input);
skipTo("Sec-WebSocket-Accept: ",input);
lookFor("s3pPLMBiTxaQ9kYGzzhZRbK+xOo=",input);
@ -1233,9 +1233,9 @@ public class WebSocketMessageRFC6455Test
assertTrue(__serverWebSocket.awaitConnected(1000));
assertNotNull(__serverWebSocket.connection);
__serverWebSocket.getConnection().setMaxBinaryMessageSize(15);
output.write(0x02);
output.write(0x94);
output.write(0xff);
@ -1246,7 +1246,7 @@ public class WebSocketMessageRFC6455Test
for (int i=0;i<bytes.length;i++)
output.write(bytes[i]^0xff);
output.flush();
assertEquals(0x80|WebSocketConnectionRFC6455.OP_CLOSE,input.read());
assertEquals(19,input.read());
int code=(0xff&input.read())*0x100+(0xff&input.read());
@ -1283,7 +1283,7 @@ public class WebSocketMessageRFC6455Test
assertTrue(__serverWebSocket.awaitConnected(1000));
assertNotNull(__serverWebSocket.connection);
assertEquals(0x81,input.read());
assertEquals(0x0f,input.read());
lookFor("sent on connect",input);
@ -1302,8 +1302,8 @@ public class WebSocketMessageRFC6455Test
output.write(0xff);
output.write(0xff);
output.flush();
assertTrue(__serverWebSocket.awaitDisconnected(5000));
try
{
@ -1346,12 +1346,12 @@ public class WebSocketMessageRFC6455Test
assertTrue(__serverWebSocket.awaitConnected(1000));
assertNotNull(__serverWebSocket.connection);
assertEquals(0x81,input.read());
assertEquals(0x0f,input.read());
lookFor("sent on connect",input);
socket.close();
assertTrue(__serverWebSocket.awaitDisconnected(500));
try
@ -1362,7 +1362,7 @@ public class WebSocketMessageRFC6455Test
catch(IOException e)
{
assertTrue(true);
}
}
}
@Test
@ -1395,19 +1395,19 @@ public class WebSocketMessageRFC6455Test
assertTrue(__serverWebSocket.awaitConnected(1000));
assertNotNull(__serverWebSocket.connection);
assertEquals(0x81,input.read());
assertEquals(0x0f,input.read());
lookFor("sent on connect",input);
socket.shutdownOutput();
assertTrue(__serverWebSocket.awaitDisconnected(500));
assertEquals(0x88,input.read());
assertEquals(0x00,input.read());
assertEquals(-1,input.read());
// look for broken pipe
try
{
@ -1420,24 +1420,24 @@ public class WebSocketMessageRFC6455Test
// expected
}
}
@Test
public void testParserAndGenerator() throws Exception
{
String message = "0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF";
final AtomicReference<String> received = new AtomicReference<String>();
ByteArrayEndPoint endp = new ByteArrayEndPoint(new byte[0],4096);
WebSocketGeneratorRFC6455 gen = new WebSocketGeneratorRFC6455(new WebSocketBuffers(8096),endp,null);
byte[] data = message.getBytes(StringUtil.__UTF8);
gen.addFrame((byte)0x8,(byte)0x4,data,0,data.length);
endp = new ByteArrayEndPoint(endp.getOut().asArray(),4096);
WebSocketParserD13 parser = new WebSocketParserD13(new WebSocketBuffers(8096),endp,new WebSocketParser.FrameHandler()
WebSocketParserRFC6455 parser = new WebSocketParserRFC6455(new WebSocketBuffers(8096),endp,new WebSocketParser.FrameHandler()
{
public void onFrame(byte flags, byte opcode, Buffer buffer)
{
@ -1449,12 +1449,12 @@ public class WebSocketMessageRFC6455Test
}
},false);
parser.parseNext();
assertEquals(message,received.get());
}
@Test
public void testParserAndGeneratorMasked() throws Exception
{
@ -1463,14 +1463,14 @@ public class WebSocketMessageRFC6455Test
ByteArrayEndPoint endp = new ByteArrayEndPoint(new byte[0],4096);
MaskGen maskGen = new RandomMaskGen();
WebSocketGeneratorRFC6455 gen = new WebSocketGeneratorRFC6455(new WebSocketBuffers(8096),endp,maskGen);
byte[] data = message.getBytes(StringUtil.__UTF8);
gen.addFrame((byte)0x8,(byte)0x1,data,0,data.length);
endp = new ByteArrayEndPoint(endp.getOut().asArray(),4096);
WebSocketParserD13 parser = new WebSocketParserD13(new WebSocketBuffers(8096),endp,new WebSocketParser.FrameHandler()
WebSocketParserRFC6455 parser = new WebSocketParserRFC6455(new WebSocketBuffers(8096),endp,new WebSocketParser.FrameHandler()
{
public void onFrame(byte flags, byte opcode, Buffer buffer)
{
@ -1481,13 +1481,13 @@ public class WebSocketMessageRFC6455Test
{
}
},true);
parser.parseNext();
assertEquals(message,received.get());
}
private void lookFor(String string,InputStream in)
throws IOException
{
@ -1535,7 +1535,7 @@ public class WebSocketMessageRFC6455Test
state=0;
}
}
private static class TestWebSocket implements WebSocket.OnFrame, WebSocket.OnBinaryMessage, WebSocket.OnTextMessage
{
@ -1556,7 +1556,7 @@ public class WebSocketMessageRFC6455Test
{
this.connection = connection;
}
public void onOpen(Connection connection)
{
if (_onConnect)
@ -1582,14 +1582,14 @@ public class WebSocketMessageRFC6455Test
{
return disconnected.await(time, TimeUnit.MILLISECONDS);
}
public void onClose(int code,String message)
{
disconnected.countDown();
}
public boolean onFrame(byte flags, byte opcode, byte[] data, int offset, int length)
{
{
if (_echo)
{
switch(opcode)
@ -1598,7 +1598,7 @@ public class WebSocketMessageRFC6455Test
case WebSocketConnectionRFC6455.OP_PING:
case WebSocketConnectionRFC6455.OP_PONG:
break;
default:
try
{
@ -1642,7 +1642,7 @@ public class WebSocketMessageRFC6455Test
e.printStackTrace();
}
}
if (_aggregate)
{
try

View File

@ -35,6 +35,8 @@ public class WebSocketOverSSLTest
{
private Server _server;
private int _port;
private QueuedThreadPool _threadPool;
private WebSocketClientFactory _wsFactory;
private WebSocket.Connection _connection;
private void startServer(final WebSocket webSocket) throws Exception
@ -61,13 +63,18 @@ public class WebSocketOverSSLTest
{
Assert.assertTrue(_server.isStarted());
WebSocketClientFactory factory = new WebSocketClientFactory(new QueuedThreadPool(), new ZeroMaskGen());
SslContextFactory cf = factory.getSslContextFactory();
_threadPool = new QueuedThreadPool();
_threadPool.setName("wsc-" + _threadPool.getName());
_threadPool.start();
_wsFactory = new WebSocketClientFactory(_threadPool, new ZeroMaskGen());
SslContextFactory cf = _wsFactory.getSslContextFactory();
cf.setKeyStorePath(MavenTestingUtils.getTestResourceFile("keystore").getAbsolutePath());
cf.setKeyStorePassword("storepwd");
cf.setKeyManagerPassword("keypwd");
factory.start();
WebSocketClient client = new WebSocketClient(factory);
_wsFactory.start();
WebSocketClient client = new WebSocketClient(_wsFactory);
_connection = client.open(new URI("wss://localhost:" + _port), webSocket).get(5, TimeUnit.SECONDS);
}
@ -76,6 +83,13 @@ public class WebSocketOverSSLTest
{
if (_connection != null)
_connection.close();
if (_wsFactory != null)
_wsFactory.stop();
if (_threadPool != null)
_threadPool.stop();
if (_server != null)
{
_server.stop();

View File

@ -15,8 +15,6 @@
*******************************************************************************/
package org.eclipse.jetty.websocket;
import static org.junit.Assert.*;
import java.util.ArrayList;
import java.util.List;
@ -30,12 +28,16 @@ import org.eclipse.jetty.util.Utf8StringBuilder;
import org.junit.Before;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
public class WebSocketParserRFC6455Test
{
private ByteArrayEndPoint _endPoint;
private MaskedByteArrayBuffer _in;
private Handler _handler;
private WebSocketParserD13 _parser;
private WebSocketParserRFC6455 _parser;
private byte[] _mask = new byte[] {(byte)0x00,(byte)0xF0,(byte)0x0F,(byte)0xFF};
private int _m;
@ -45,7 +47,7 @@ public class WebSocketParserRFC6455Test
{
super(4096);
}
public void sendMask()
{
super.poke(putIndex(),_mask,0,4);
@ -63,7 +65,7 @@ public class WebSocketParserRFC6455Test
{
super.put(b);
}
@Override
public void put(byte b)
{
@ -87,10 +89,10 @@ public class WebSocketParserRFC6455Test
{
return put(b,0,b.length);
}
};
@Before
public void setUp() throws Exception
{
@ -98,10 +100,10 @@ public class WebSocketParserRFC6455Test
_endPoint = new ByteArrayEndPoint();
_endPoint.setNonBlocking(true);
_handler = new Handler();
_parser=new WebSocketParserD13(buffers, _endPoint,_handler,true);
_parser=new WebSocketParserRFC6455(buffers, _endPoint,_handler,true);
_parser.setFakeFragments(false);
_in = new MaskedByteArrayBuffer();
_endPoint.setIn(_in);
}
@ -127,7 +129,7 @@ public class WebSocketParserRFC6455Test
_parser.returnBuffer();
assertTrue(_parser.getBuffer()==null);
}
@Test
public void testShortText() throws Exception
{
@ -147,7 +149,7 @@ public class WebSocketParserRFC6455Test
_parser.returnBuffer();
assertTrue(_parser.getBuffer()==null);
}
@Test
public void testShortUtf8() throws Exception
{
@ -169,7 +171,7 @@ public class WebSocketParserRFC6455Test
assertTrue(_parser.isBufferEmpty());
assertTrue(_parser.getBuffer()==null);
}
@Test
public void testMediumText() throws Exception
{
@ -177,9 +179,9 @@ public class WebSocketParserRFC6455Test
for (int i=0;i<4;i++)
string = string+string;
string += ". The end.";
byte[] bytes = string.getBytes(StringUtil.__UTF8);
_in.putUnmasked((byte)0x81);
_in.putUnmasked((byte)(0x80|0x7E));
_in.putUnmasked((byte)(bytes.length>>8));
@ -197,21 +199,21 @@ public class WebSocketParserRFC6455Test
assertTrue(_parser.isBufferEmpty());
assertTrue(_parser.getBuffer()==null);
}
@Test
public void testLongText() throws Exception
{
WebSocketBuffers buffers = new WebSocketBuffers(0x20000);
ByteArrayEndPoint endPoint = new ByteArrayEndPoint();
WebSocketParserD13 parser=new WebSocketParserD13(buffers, endPoint,_handler,false);
WebSocketParserRFC6455 parser=new WebSocketParserRFC6455(buffers, endPoint,_handler,false);
ByteArrayBuffer in = new ByteArrayBuffer(0x20000);
endPoint.setIn(in);
String string = "Hell\uFF4f Big W\uFF4Frld ";
for (int i=0;i<12;i++)
string = string+string;
string += ". The end.";
byte[] bytes = string.getBytes("UTF-8");
_in.sendMask();
@ -269,7 +271,7 @@ public class WebSocketParserRFC6455Test
{
// Buffers are only 1024, so this frame is too large
_parser.setFakeFragments(false);
_in.putUnmasked((byte)0x81);
_in.putUnmasked((byte)(0x80|0x7E));
_in.putUnmasked((byte)(2048>>8));
@ -280,8 +282,8 @@ public class WebSocketParserRFC6455Test
assertTrue(progress>0);
assertEquals(WebSocketConnectionRFC6455.CLOSE_POLICY_VIOLATION,_handler._code);
for (int i=0;i<2048;i++)
_in.put((byte)'a');
progress =_parser.parseNext();
@ -289,7 +291,7 @@ public class WebSocketParserRFC6455Test
assertTrue(progress>0);
assertEquals(0,_handler._data.size());
assertEquals(0,_handler._utf8.length());
_handler._code=0;
_in.putUnmasked((byte)0x81);
@ -310,7 +312,7 @@ public class WebSocketParserRFC6455Test
{
// Buffers are only 1024, so this frame will be fake fragmented
_parser.setFakeFragments(true);
_in.putUnmasked((byte)0x81);
_in.putUnmasked((byte)(0x80|0x7E));
_in.putUnmasked((byte)(2048>>8));
@ -318,7 +320,7 @@ public class WebSocketParserRFC6455Test
_in.sendMask();
for (int i=0;i<2048;i++)
_in.put((byte)('a'+i%26));
int progress =_parser.parseNext();
assertTrue(progress>0);
@ -355,21 +357,21 @@ public class WebSocketParserRFC6455Test
_parser.returnBuffer();
assertTrue(_parser.isBufferEmpty());
assertTrue(_parser.getBuffer()==null);
_in.clear();
_in.put(bytes);
_endPoint.setIn(_in);
progress =_parser.parseNext();
assertTrue(progress>0);
_endPoint.shutdownInput();
progress =_parser.parseNext();
assertEquals(-1,progress);
}
private class Handler implements WebSocketParser.FrameHandler
{
Utf8StringBuilder _utf8 = new Utf8StringBuilder();

View File

@ -17,12 +17,14 @@ package org.eclipse.jetty.websocket.helper;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import org.eclipse.jetty.websocket.WebSocket;
public class CaptureSocket implements WebSocket, WebSocket.OnTextMessage
public class CaptureSocket implements WebSocket.OnTextMessage
{
private Connection conn;
private final CountDownLatch latch = new CountDownLatch(1);
public List<String> messages;
public CaptureSocket()
@ -30,13 +32,9 @@ public class CaptureSocket implements WebSocket, WebSocket.OnTextMessage
messages = new ArrayList<String>();
}
public boolean isConnected()
public boolean awaitConnected(long timeout) throws InterruptedException
{
if (conn == null)
{
return false;
}
return conn.isOpen();
return latch.await(timeout, TimeUnit.MILLISECONDS);
}
public void onMessage(String data)
@ -47,11 +45,10 @@ public class CaptureSocket implements WebSocket, WebSocket.OnTextMessage
public void onOpen(Connection connection)
{
this.conn = connection;
latch.countDown();
}
public void onClose(int closeCode, String message)
{
this.conn = null;
}
}
}

View File

@ -15,8 +15,6 @@
*******************************************************************************/
package org.eclipse.jetty.websocket.helper;
import static org.hamcrest.Matchers.*;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
@ -32,6 +30,8 @@ import org.eclipse.jetty.io.ByteArrayBuffer;
import org.eclipse.jetty.util.TypeUtil;
import org.junit.Assert;
import static org.hamcrest.Matchers.is;
public class SafariD00
{
private URI uri;
@ -48,7 +48,7 @@ public class SafariD00
/**
* Open the Socket to the destination endpoint and
*
*
* @return the open java Socket.
* @throws IOException
*/
@ -65,7 +65,7 @@ public class SafariD00
/**
* Issue an Http websocket (Draft-0) upgrade request using the Safari particulars.
*
*
* @throws UnsupportedEncodingException
*/
public void issueHandshake() throws IOException
@ -96,6 +96,8 @@ public class SafariD00
InputStreamReader reader = new InputStreamReader(in);
BufferedReader br = new BufferedReader(reader);
socket.setSoTimeout(5000);
boolean foundEnd = false;
String line;
while (!foundEnd)

View File

@ -5,7 +5,6 @@
<version>8.1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>org.eclipse.jetty</groupId>
<artifactId>test-jetty-webapp</artifactId>
<name>Test :: Jetty Test Webapp</name>
<packaging>war</packaging>