Author: david.lloyd(a)jboss.com
Date: 2010-02-28 16:14:06 -0500 (Sun, 28 Feb 2010)
New Revision: 5772
Added:
remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/remote/AbstractClientMessageHandler.java
remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/remote/AbstractMessageHandler.java
Modified:
remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/EndpointImpl.java
remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/RemotingOptions.java
remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/remote/ClientAuthenticationHandler.java
remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/remote/ClientGreetingHandler.java
remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/remote/ClientOpenListener.java
remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/remote/InboundRequestInputHandler.java
remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/remote/OutboundRequestHandler.java
remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/remote/RemoteConnection.java
remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/remote/RemoteConnectionHandler.java
remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/remote/RemoteMessageHandler.java
remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/remote/RemoteProtocol.java
remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/remote/SaslUtils.java
remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/remote/ServerAuthenticationHandler.java
remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/remote/ServerGreetingHandler.java
remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/remote/ServerInitialAuthenticationHandler.java
remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/remote/ServerOpenListener.java
remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/security/SimpleClientCallbackHandler.java
remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/spi/AbstractHandleableCloseable.java
remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/spi/ConnectionProviderContext.java
remoting3/trunk/jboss-remoting/src/test/java/org/jboss/remoting3/test/RemoteTestCase.java
remoting3/trunk/jboss-remoting/src/test/resources/remoting.properties
Log:
Make sure DIGEST-MD5 and CRAM-MD5 both work
Modified:
remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/EndpointImpl.java
===================================================================
---
remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/EndpointImpl.java 2010-02-28
15:51:38 UTC (rev 5771)
+++
remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/EndpointImpl.java 2010-02-28
21:14:06 UTC (rev 5772)
@@ -534,10 +534,19 @@
}
public IoFuture<? extends Connection> connect(final URI destination, final
OptionMap connectOptions) throws IOException {
- return connect(destination, connectOptions, new
SimpleClientCallbackHandler(connectOptions.get(RemotingOptions.AUTH_USER_NAME),
connectOptions.get(RemotingOptions.AUTH_REALM), null));
+ final String uriUserInfo = destination.getUserInfo();
+ final OptionMap finalMap;
+ if (uriUserInfo != null) {
+ final OptionMap.Builder builder =
OptionMap.builder().addAll(connectOptions);
+ builder.set(RemotingOptions.AUTH_USER_NAME, uriUserInfo);
+ finalMap = builder.getMap();
+ } else {
+ finalMap = connectOptions;
+ }
+ return doConnect(destination, connectOptions, new
SimpleClientCallbackHandler(finalMap.get(RemotingOptions.AUTH_USER_NAME),
finalMap.get(RemotingOptions.AUTH_REALM), null));
}
- public IoFuture<? extends Connection> connect(final URI destination, final
OptionMap connectOptions, final CallbackHandler callbackHandler) throws IOException {
+ private IoFuture<? extends Connection> doConnect(final URI destination, final
OptionMap connectOptions, final CallbackHandler callbackHandler) throws IOException {
final SecurityManager sm = System.getSecurityManager();
if (sm != null) {
sm.checkPermission(CONNECT_PERM);
@@ -556,10 +565,28 @@
return futureResult.getIoFuture();
}
+ public IoFuture<? extends Connection> connect(final URI destination, final
OptionMap connectOptions, final CallbackHandler callbackHandler) throws IOException {
+ final String uriUserInfo = destination.getUserInfo();
+ final OptionMap finalMap;
+ if (uriUserInfo != null) {
+ final OptionMap.Builder builder =
OptionMap.builder().addAll(connectOptions);
+ builder.set(RemotingOptions.AUTH_USER_NAME, uriUserInfo);
+ finalMap = builder.getMap();
+ } else {
+ finalMap = connectOptions;
+ }
+ return doConnect(destination, finalMap, callbackHandler);
+ }
+
public IoFuture<? extends Connection> connect(final URI destination, final
OptionMap connectOptions, final String userName, final String realmName, final char[]
password) throws IOException {
- final String actualUserName = userName != null ? userName :
connectOptions.get(RemotingOptions.AUTH_USER_NAME);
+ final String uriUserInfo = destination.getUserInfo();
+ final String actualUserName = userName != null ? userName : uriUserInfo != null ?
uriUserInfo : connectOptions.get(RemotingOptions.AUTH_USER_NAME);
final String actualUserRealm = realmName != null ? realmName :
connectOptions.get(RemotingOptions.AUTH_REALM);
- return connect(destination, connectOptions, new
SimpleClientCallbackHandler(actualUserName, actualUserRealm, password));
+ final OptionMap.Builder builder = OptionMap.builder().addAll(connectOptions);
+ if (actualUserName != null) builder.set(RemotingOptions.AUTH_USER_NAME,
actualUserName);
+ if (actualUserRealm != null) builder.set(RemotingOptions.AUTH_REALM,
actualUserRealm);
+ final OptionMap finalMap = builder.getMap();
+ return doConnect(destination, finalMap, new
SimpleClientCallbackHandler(actualUserName, actualUserRealm, password));
}
public ConnectionProviderRegistration addConnectionProvider(final String uriScheme,
final ConnectionProviderFactory providerFactory) {
@@ -695,6 +722,10 @@
public <T> T getProtocolServiceProvider(final ProtocolServiceType<T>
serviceType, final String name) {
return getMapFor(serviceType).get(name);
}
+
+ public String getEndpointName() {
+ return getName();
+ }
}
private class ConnectionProviderRegistrationImpl extends
AbstractHandleableCloseable<Registration> implements ConnectionProviderRegistration
{
Modified:
remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/RemotingOptions.java
===================================================================
---
remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/RemotingOptions.java 2010-02-28
15:51:38 UTC (rev 5771)
+++
remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/RemotingOptions.java 2010-02-28
21:14:06 UTC (rev 5772)
@@ -143,9 +143,4 @@
* Specify the name of a preregistered server authentication provider to use.
*/
public static final Option<String> AUTHENTICATION_PROVIDER =
Option.simple(RemotingOptions.class, "AUTHENTICATION_PROVIDER", String.class);
-
- /**
- * Specify a set of SASL server mechanisms to allow. If not specified, no mechanisms
will be excluded.
- */
- public static final Option<Sequence<String>> SASL_SERVER_MECHANISMS =
Option.sequence(RemotingOptions.class, "SASL_SERVER_MECHANISMS", String.class);
}
Added:
remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/remote/AbstractClientMessageHandler.java
===================================================================
---
remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/remote/AbstractClientMessageHandler.java
(rev 0)
+++
remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/remote/AbstractClientMessageHandler.java 2010-02-28
21:14:06 UTC (rev 5772)
@@ -0,0 +1,41 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2010, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site:
http://www.fsf.org.
+ */
+
+package org.jboss.remoting3.remote;
+
+import java.io.IOException;
+import org.jboss.remoting3.spi.ConnectionHandlerFactory;
+import org.jboss.xnio.Result;
+
+abstract class AbstractClientMessageHandler extends AbstractMessageHandler {
+ private final Result<ConnectionHandlerFactory> result;
+
+ protected AbstractClientMessageHandler(final RemoteConnection remoteConnection, final
Result<ConnectionHandlerFactory> result) {
+ super(remoteConnection);
+ this.result = result;
+ }
+
+ public void handleException(final IOException e) {
+ result.setException(e);
+ super.handleException(e);
+ }
+}
Added:
remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/remote/AbstractMessageHandler.java
===================================================================
---
remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/remote/AbstractMessageHandler.java
(rev 0)
+++
remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/remote/AbstractMessageHandler.java 2010-02-28
21:14:06 UTC (rev 5772)
@@ -0,0 +1,50 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2010, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site:
http://www.fsf.org.
+ */
+
+package org.jboss.remoting3.remote;
+
+import java.io.IOException;
+import org.jboss.xnio.IoUtils;
+import org.jboss.xnio.channels.MessageHandler;
+
+abstract class AbstractMessageHandler implements MessageHandler {
+ protected final RemoteConnection remoteConnection;
+
+ protected AbstractMessageHandler(final RemoteConnection remoteConnection) {
+ this.remoteConnection = remoteConnection;
+ }
+
+ public void handleEof() {
+ try {
+ remoteConnection.getChannel().shutdownReads();
+ } catch (IOException e) {
+ RemoteConnectionHandler.log.trace(e, "Failed to shut down reads for
%s", remoteConnection);
+ }
+ remoteConnection.readDone();
+ IoUtils.safeClose(remoteConnection);
+ }
+
+ public void handleException(final IOException e) {
+ RemoteConnectionHandler.log.trace(e, "Received exception from %s",
remoteConnection);
+ IoUtils.safeClose(remoteConnection);
+ }
+}
Modified:
remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/remote/ClientAuthenticationHandler.java
===================================================================
---
remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/remote/ClientAuthenticationHandler.java 2010-02-28
15:51:38 UTC (rev 5771)
+++
remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/remote/ClientAuthenticationHandler.java 2010-02-28
21:14:06 UTC (rev 5772)
@@ -22,7 +22,6 @@
package org.jboss.remoting3.remote;
-import java.io.EOFException;
import java.io.IOException;
import java.nio.ByteBuffer;
import org.jboss.marshalling.MarshallerFactory;
@@ -35,18 +34,18 @@
import org.jboss.xnio.Buffers;
import org.jboss.xnio.IoUtils;
import org.jboss.xnio.Result;
-import org.jboss.xnio.channels.MessageHandler;
import javax.security.sasl.SaslClient;
import javax.security.sasl.SaslException;
-final class ClientAuthenticationHandler implements MessageHandler {
+final class ClientAuthenticationHandler extends AbstractClientMessageHandler {
private final RemoteConnection remoteConnection;
private final SaslClient saslClient;
private final Result<ConnectionHandlerFactory> factoryResult;
- public ClientAuthenticationHandler(final RemoteConnection remoteConnection, final
SaslClient saslClient, final Result<ConnectionHandlerFactory> factoryResult) {
+ ClientAuthenticationHandler(final RemoteConnection remoteConnection, final SaslClient
saslClient, final Result<ConnectionHandlerFactory> factoryResult) {
+ super(remoteConnection, factoryResult);
this.remoteConnection = remoteConnection;
this.saslClient = saslClient;
this.factoryResult = factoryResult;
@@ -55,54 +54,92 @@
public void handleMessage(final ByteBuffer buffer) {
final byte msgType = buffer.get();
switch (msgType) {
- case RemoteProtocol.AUTH_CHALLENGE:
- case RemoteProtocol.AUTH_COMPLETE: {
+ case RemoteProtocol.AUTH_CHALLENGE: {
+ RemoteConnectionHandler.log.trace("Received challenge
message");
+ final boolean clientComplete = saslClient.isComplete();
+ if (clientComplete) {
+ RemoteConnectionHandler.log.trace("Received extra auth challenge
message on %s after completion", remoteConnection);
+ factoryResult.setException(new SaslException("Received extra
auth message after completion"));
+ IoUtils.safeClose(remoteConnection);
+ return;
+ }
final byte[] response;
+ final byte[] challenge = Buffers.take(buffer, buffer.remaining());
try {
- response = saslClient.evaluateChallenge(Buffers.take(buffer,
buffer.remaining()));
+ response = saslClient.evaluateChallenge(challenge);
+ if (msgType == RemoteProtocol.AUTH_COMPLETE && response !=
null && response.length > 0) {
+ RemoteConnectionHandler.log.trace("Received extra auth
message on %s", remoteConnection);
+ factoryResult.setException(new SaslException("Received extra
auth message after completion"));
+ IoUtils.safeClose(remoteConnection);
+ return;
+ }
} catch (SaslException e) {
- // todo log it
+ RemoteConnectionHandler.log.trace(e, "Authentication
error");
factoryResult.setException(e);
+ try {
+ remoteConnection.shutdownWritesBlocking();
+ } catch (IOException e1) {
+ RemoteConnectionHandler.log.trace(e, "Unable to shut down
writes");
+ }
+ return;
+ }
+ try {
+ RemoteConnectionHandler.log.trace("Sending SASL
response");
+ remoteConnection.sendAuthMessage(RemoteProtocol.AUTH_RESPONSE,
response);
+ } catch (IOException e) {
+ factoryResult.setException(e);
+ RemoteConnectionHandler.log.trace("Failed to send auth response
message on %s", remoteConnection);
IoUtils.safeClose(remoteConnection);
return;
}
- if (msgType == RemoteProtocol.AUTH_COMPLETE) {
- if ((response != null || response.length > 0)) {
- // todo log extraneous message
+ return;
+ }
+ case RemoteProtocol.AUTH_COMPLETE: {
+ RemoteConnectionHandler.log.trace("Received auth complete
message");
+ final boolean clientComplete = saslClient.isComplete();
+ final byte[] challenge = Buffers.take(buffer, buffer.remaining());
+ if (! clientComplete) try {
+ final byte[] response = saslClient.evaluateChallenge(challenge);
+ if (response != null && response.length > 0) {
+ RemoteConnectionHandler.log.trace("Received extra auth
message on %s", remoteConnection);
+ factoryResult.setException(new SaslException("Received extra
auth message after completion"));
IoUtils.safeClose(remoteConnection);
return;
}
- // auth complete.
- factoryResult.setResult(new ConnectionHandlerFactory() {
- public ConnectionHandler createInstance(final
ConnectionHandlerContext connectionContext) {
- // this happens immediately.
- final MarshallerFactory marshallerFactory =
Marshalling.getMarshallerFactory("river");
- final MarshallingConfiguration marshallingConfiguration = new
MarshallingConfiguration();
- final RemoteConnectionHandler connectionHandler = new
RemoteConnectionHandler(connectionContext, remoteConnection, marshallerFactory,
marshallingConfiguration);
- remoteConnection.addCloseHandler(new
CloseHandler<Object>() {
- public void handleClose(final Object closed) {
- IoUtils.safeClose(connectionHandler);
- }
- });
- remoteConnection.setMessageHandler(new
RemoteMessageHandler(connectionHandler, remoteConnection));
- return connectionHandler;
- }
- });
+ if (! saslClient.isComplete()) {
+ RemoteConnectionHandler.log.trace("Client not complete after
processing auth complete message on %s", remoteConnection);
+ factoryResult.setException(new SaslException("Client not
complete after processing auth complete message"));
+ IoUtils.safeClose(remoteConnection);
+ return;
+ }
+ } catch (SaslException e) {
+ RemoteConnectionHandler.log.trace(e, "Authentication
error");
+ factoryResult.setException(e);
+ try {
+ remoteConnection.shutdownWritesBlocking();
+ } catch (IOException e1) {
+ RemoteConnectionHandler.log.trace(e, "Unable to shut down
writes");
+ }
return;
}
- break;
+ // auth complete.
+ factoryResult.setResult(new ConnectionHandlerFactory() {
+ public ConnectionHandler createInstance(final
ConnectionHandlerContext connectionContext) {
+ // this happens immediately.
+ final MarshallerFactory marshallerFactory =
Marshalling.getMarshallerFactory("river");
+ final MarshallingConfiguration marshallingConfiguration = new
MarshallingConfiguration();
+ final RemoteConnectionHandler connectionHandler = new
RemoteConnectionHandler(connectionContext, remoteConnection, marshallerFactory,
marshallingConfiguration);
+ remoteConnection.addCloseHandler(new CloseHandler<Object>()
{
+ public void handleClose(final Object closed) {
+ IoUtils.safeClose(connectionHandler);
+ }
+ });
+ remoteConnection.setMessageHandler(new
RemoteMessageHandler(connectionHandler, remoteConnection));
+ return connectionHandler;
+ }
+ });
+ return;
}
}
}
-
- public void handleEof() {
- factoryResult.setException(new EOFException("End of file on input"));
- IoUtils.safeClose(remoteConnection);
- }
-
- public void handleException(final IOException e) {
- // todo log it
- factoryResult.setException(e);
- IoUtils.safeClose(remoteConnection);
- }
}
Modified:
remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/remote/ClientGreetingHandler.java
===================================================================
---
remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/remote/ClientGreetingHandler.java 2010-02-28
15:51:38 UTC (rev 5771)
+++
remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/remote/ClientGreetingHandler.java 2010-02-28
21:14:06 UTC (rev 5772)
@@ -22,7 +22,6 @@
package org.jboss.remoting3.remote;
-import java.io.EOFException;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.ArrayList;
@@ -31,23 +30,21 @@
import org.jboss.remoting3.RemotingOptions;
import org.jboss.remoting3.spi.ConnectionHandlerFactory;
import org.jboss.xnio.Buffers;
-import org.jboss.xnio.IoUtils;
-import org.jboss.xnio.Option;
import org.jboss.xnio.OptionMap;
import org.jboss.xnio.Result;
-import org.jboss.xnio.channels.MessageHandler;
import javax.security.auth.callback.CallbackHandler;
import javax.security.sasl.Sasl;
import javax.security.sasl.SaslClient;
import javax.security.sasl.SaslException;
-final class ClientGreetingHandler implements MessageHandler {
+final class ClientGreetingHandler extends AbstractClientMessageHandler {
private final RemoteConnection connection;
private final Result<ConnectionHandlerFactory> factoryResult;
private final CallbackHandler callbackHandler;
- public ClientGreetingHandler(final RemoteConnection connection, final
Result<ConnectionHandlerFactory> factoryResult, final CallbackHandler
callbackHandler) {
+ ClientGreetingHandler(final RemoteConnection connection, final
Result<ConnectionHandlerFactory> factoryResult, final CallbackHandler
callbackHandler) {
+ super(connection, factoryResult);
this.connection = connection;
this.factoryResult = factoryResult;
this.callbackHandler = callbackHandler;
@@ -55,6 +52,7 @@
public void handleMessage(final ByteBuffer buffer) {
List<String> saslMechs = new ArrayList<String>();
+ String remoteEndpointName = "endpoint";
switch (buffer.get()) {
case RemoteProtocol.GREETING: {
while (buffer.hasRemaining()) {
@@ -71,6 +69,10 @@
saslMechs.add(Buffers.getModifiedUtf8(Buffers.slice(buffer,
len)));
break;
}
+ case RemoteProtocol.GREETING_ENDPOINT_NAME: {
+ remoteEndpointName =
Buffers.getModifiedUtf8(Buffers.slice(buffer, len));
+ break;
+ }
default: {
// unknown, skip it for forward compatibility.
Buffers.skip(buffer, len);
@@ -81,37 +83,49 @@
// OK now send our authentication request
final OptionMap optionMap = connection.getOptionMap();
final String userName = optionMap.get(RemotingOptions.AUTH_USER_NAME);
- final String hostName =
connection.getChannel().getPeerAddress().getHostName();
final Map<String, ?> propertyMap =
SaslUtils.createPropertyMap(optionMap);
final SaslClient saslClient;
try {
- saslClient = Sasl.createSaslClient(saslMechs.toArray(new
String[saslMechs.size()]), userName == null ? "anonymous" : userName,
"remote", hostName, propertyMap, callbackHandler);
+ saslClient = Sasl.createSaslClient(saslMechs.toArray(new
String[saslMechs.size()]), userName, "remote", remoteEndpointName, propertyMap,
callbackHandler);
} catch (SaslException e) {
factoryResult.setException(e);
- // todo log exception @ error
- // todo send "goodbye" & close
- IoUtils.safeClose(connection);
+ RemoteConnectionHandler.log.trace(e, "Client connect
authentication error");
+ try {
+ remoteConnection.shutdownWritesBlocking();
+ } catch (IOException e1) {
+ RemoteConnectionHandler.log.trace(e1, "Failed to shutdown
writes on %s", remoteConnection);
+ }
return;
}
+ final String mechanismName = saslClient.getMechanismName();
+ RemoteConnectionHandler.log.trace("Sasl mechanism selected:
%s", mechanismName);
+ final ByteBuffer outBuf = connection.allocate();
+ try {
+ outBuf.putInt(0);
+ outBuf.put(RemoteProtocol.AUTH_REQUEST);
+ Buffers.putModifiedUtf8(outBuf, mechanismName);
+ outBuf.flip();
+ connection.sendBlocking(outBuf);
+ connection.flushBlocking();
+ } catch (IOException e) {
+ RemoteConnectionHandler.log.trace(e, "Failed to send auth
request on %s", remoteConnection);
+ factoryResult.setException(e);
+ return;
+ } finally {
+ connection.free(outBuf);
+ }
connection.setMessageHandler(new ClientAuthenticationHandler(connection,
saslClient, factoryResult));
return;
}
default: {
- // todo log invalid greeting
- IoUtils.safeClose(connection);
+ RemoteConnectionHandler.log.warn("Received invalid greeting packet
on %s", remoteConnection);
+ try {
+ remoteConnection.shutdownWritesBlocking();
+ } catch (IOException e1) {
+ RemoteConnectionHandler.log.trace(e1, "Failed to shutdown writes
on %s", remoteConnection);
+ }
return;
}
}
}
-
- public void handleEof() {
- factoryResult.setException(new EOFException("End of file on input"));
- IoUtils.safeClose(connection);
- }
-
- public void handleException(final IOException e) {
- // todo log it
- factoryResult.setException(e);
- IoUtils.safeClose(connection);
- }
}
\ No newline at end of file
Modified:
remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/remote/ClientOpenListener.java
===================================================================
---
remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/remote/ClientOpenListener.java 2010-02-28
15:51:38 UTC (rev 5771)
+++
remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/remote/ClientOpenListener.java 2010-02-28
21:14:06 UTC (rev 5772)
@@ -43,7 +43,7 @@
private final Result<ConnectionHandlerFactory> factoryResult;
private final CallbackHandler callbackHandler;
- public ClientOpenListener(final OptionMap optionMap, final ConnectionProviderContext
connectionProviderContext, final Result<ConnectionHandlerFactory> factoryResult,
final CallbackHandler callbackHandler) {
+ ClientOpenListener(final OptionMap optionMap, final ConnectionProviderContext
connectionProviderContext, final Result<ConnectionHandlerFactory> factoryResult,
final CallbackHandler callbackHandler) {
this.optionMap = optionMap;
this.connectionProviderContext = connectionProviderContext;
this.factoryResult = factoryResult;
@@ -60,24 +60,39 @@
// Send client greeting packet...
final ByteBuffer buffer = connection.allocate();
- try {
- // length placeholder
- buffer.putInt(0);
- // version ID
- GreetingUtils.writeByte(buffer, RemoteProtocol.GREETING_VERSION,
RemoteProtocol.VERSION);
- // that's it!
- buffer.flip();
- connection.sendBlocking(buffer);
- } catch (IOException e1) {
- // todo log it
- factoryResult.setException(e1);
- IoUtils.safeClose(connection);
- } finally {
- connection.free(buffer);
- }
+ // length placeholder
+ buffer.putInt(0);
+ // version ID
+ GreetingUtils.writeByte(buffer, RemoteProtocol.GREETING_VERSION,
RemoteProtocol.VERSION);
+ // that's it!
+ buffer.flip();
+ buffer.putInt(0, buffer.remaining() - 4);
+ channel.getWriteSetter().set(new
ChannelListener<ConnectedStreamChannel<InetSocketAddress>>() {
+ public void handleEvent(final ConnectedStreamChannel<InetSocketAddress>
channel) {
+ for (;;) {
+ while (buffer.hasRemaining()) {
+ final int res;
+ try {
+ res = channel.write(buffer);
+ } catch (IOException e1) {
+ IoUtils.safeClose(connection);
+ connection.free(buffer);
+ return;
+ }
+ if (res == 0) {
+ channel.resumeWrites();
+ return;
+ }
+ }
+ connection.free(buffer);
+ channel.resumeReads();
+ return;
+ }
+ }
+ });
connection.setMessageHandler(new ClientGreetingHandler(connection, factoryResult,
callbackHandler));
- // start up the read cycle
- channel.resumeReads();
+ // and send the greeting
+ channel.resumeWrites();
}
}
\ No newline at end of file
Modified:
remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/remote/InboundRequestInputHandler.java
===================================================================
---
remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/remote/InboundRequestInputHandler.java 2010-02-28
15:51:38 UTC (rev 5771)
+++
remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/remote/InboundRequestInputHandler.java 2010-02-28
21:14:06 UTC (rev 5772)
@@ -56,7 +56,7 @@
}
public void close() throws IOException {
- // todo: stream was closed, no action needed
+ // no operation
}
public String toString() {
Modified:
remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/remote/OutboundRequestHandler.java
===================================================================
---
remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/remote/OutboundRequestHandler.java 2010-02-28
15:51:38 UTC (rev 5771)
+++
remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/remote/OutboundRequestHandler.java 2010-02-28
21:14:06 UTC (rev 5772)
@@ -81,7 +81,7 @@
try {
connectionHandler.getRemoteConnection().sendBlocking(buf);
} catch (IOException e1) {
- // todo log it
+ RemoteConnectionHandler.log.trace("Send failed: %s", e1);
}
}
return outboundRequest;
Modified:
remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/remote/RemoteConnection.java
===================================================================
---
remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/remote/RemoteConnection.java 2010-02-28
15:51:38 UTC (rev 5771)
+++
remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/remote/RemoteConnection.java 2010-02-28
21:14:06 UTC (rev 5772)
@@ -34,17 +34,16 @@
import org.jboss.xnio.OptionMap;
import org.jboss.xnio.Pool;
import org.jboss.xnio.channels.Channels;
-import org.jboss.xnio.channels.ConnectedChannel;
import org.jboss.xnio.channels.ConnectedStreamChannel;
import org.jboss.xnio.channels.MessageHandler;
-import javax.security.auth.callback.CallbackHandler;
-
final class RemoteConnection extends AbstractHandleableCloseable<RemoteConnection>
implements Closeable {
private final ConnectedStreamChannel<InetSocketAddress> channel;
private final Pool<ByteBuffer> bufferPool =
Buffers.createHeapByteBufferAllocator(4096);
private final MessageHandler.Setter messageHandlerSetter;
private final OptionMap optionMap;
+ private boolean readDone;
+ private final Object writeLock = new Object();
RemoteConnection(final Executor executor, final
ConnectedStreamChannel<InetSocketAddress> channel, final OptionMap optionMap) {
super(executor);
@@ -53,7 +52,28 @@
this.optionMap = optionMap;
}
- public void close() throws IOException {
+ protected void closeAction() throws IOException {
+ synchronized (writeLock) {
+ try {
+ shutdownWritesBlocking();
+ } catch (IOException e) {
+ readDone = true;
+ writeLock.notifyAll();
+ IoUtils.safeClose(channel);
+ return;
+ }
+ while (! readDone) {
+ try {
+ writeLock.wait();
+ } catch (InterruptedException e) {
+ readDone = true;
+ writeLock.notifyAll();
+ IoUtils.safeClose(channel);
+ Thread.currentThread().interrupt();
+ throw new InterruptedIOException();
+ }
+ }
+ }
channel.close();
}
@@ -61,7 +81,7 @@
return optionMap;
}
- ConnectedChannel<InetSocketAddress> getChannel() {
+ ConnectedStreamChannel<InetSocketAddress> getChannel() {
return channel;
}
@@ -93,54 +113,60 @@
}
void sendBlockingNoClose(final ByteBuffer buffer) throws IOException {
- buffer.putInt(0, buffer.remaining() - 4);
- boolean intr = false;
- try {
- while (buffer.hasRemaining()) {
- if (channel.write(buffer) == 0) {
- try {
- channel.awaitWritable();
- } catch (InterruptedIOException e) {
- intr = Thread.interrupted();
+ synchronized (writeLock) {
+ buffer.putInt(0, buffer.remaining() - 4);
+ boolean intr = false;
+ try {
+ while (buffer.hasRemaining()) {
+ if (channel.write(buffer) == 0) {
+ try {
+ channel.awaitWritable();
+ } catch (InterruptedIOException e) {
+ intr = Thread.interrupted();
+ }
}
}
+ } finally {
+ if (intr) Thread.currentThread().interrupt();
}
- } finally {
- if (intr) Thread.currentThread().interrupt();
}
}
void flushBlocking() throws IOException {
- try {
- while (! channel.flush()) {
- channel.awaitWritable();
+ synchronized (writeLock) {
+ try {
+ while (! channel.flush()) {
+ channel.awaitWritable();
+ }
+ } catch (IOException e) {
+ IoUtils.safeClose(this);
+ throw e;
+ } catch (RuntimeException e) {
+ IoUtils.safeClose(this);
+ throw e;
+ } catch (Error e) {
+ IoUtils.safeClose(this);
+ throw e;
}
- } catch (IOException e) {
- IoUtils.safeClose(this);
- throw e;
- } catch (RuntimeException e) {
- IoUtils.safeClose(this);
- throw e;
- } catch (Error e) {
- IoUtils.safeClose(this);
- throw e;
}
}
void shutdownWritesBlocking() throws IOException {
- try {
- while (! channel.shutdownWrites()) {
- channel.awaitWritable();
+ synchronized (writeLock) {
+ try {
+ while (! channel.shutdownWrites()) {
+ channel.awaitWritable();
+ }
+ } catch (IOException e) {
+ IoUtils.safeClose(channel);
+ throw e;
+ } catch (RuntimeException e) {
+ IoUtils.safeClose(channel);
+ throw e;
+ } catch (Error e) {
+ IoUtils.safeClose(channel);
+ throw e;
}
- } catch (IOException e) {
- IoUtils.safeClose(this);
- throw e;
- } catch (RuntimeException e) {
- IoUtils.safeClose(this);
- throw e;
- } catch (Error e) {
- IoUtils.safeClose(this);
- throw e;
}
}
@@ -175,4 +201,13 @@
void shutdownReads() throws IOException {
channel.shutdownReads();
}
+
+ void readDone() {
+ synchronized (writeLock) {
+ readDone = true;
+ writeLock.notifyAll();
+ }
+ }
+
+
}
Modified:
remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/remote/RemoteConnectionHandler.java
===================================================================
---
remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/remote/RemoteConnectionHandler.java 2010-02-28
15:51:38 UTC (rev 5771)
+++
remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/remote/RemoteConnectionHandler.java 2010-02-28
21:14:06 UTC (rev 5772)
@@ -31,6 +31,7 @@
import org.jboss.marshalling.util.IntKeyMap;
import org.jboss.remoting3.IndeterminateOutcomeException;
import org.jboss.remoting3.ServiceOpenException;
+import org.jboss.remoting3.spi.AbstractHandleableCloseable;
import org.jboss.remoting3.spi.ConnectionHandler;
import org.jboss.remoting3.spi.ConnectionHandlerContext;
import org.jboss.remoting3.spi.RequestHandler;
@@ -41,10 +42,9 @@
import org.jboss.xnio.IoUtils;
import org.jboss.xnio.Pool;
import org.jboss.xnio.Result;
-import org.jboss.xnio.channels.Channels;
import org.jboss.xnio.log.Logger;
-final class RemoteConnectionHandler implements ConnectionHandler {
+final class RemoteConnectionHandler extends
AbstractHandleableCloseable<RemoteConnectionHandler> implements ConnectionHandler {
static final Logger log = Logger.getLogger("org.jboss.remoting.remote");
@@ -67,6 +67,7 @@
private final AtomicBoolean closed = new AtomicBoolean();
public RemoteConnectionHandler(final ConnectionHandlerContext connectionContext,
final RemoteConnection remoteConnection, final MarshallerFactory marshallerFactory, final
MarshallingConfiguration marshallingConfiguration) {
+ super(connectionContext.getConnectionProviderContext().getExecutor());
this.connectionContext = connectionContext;
this.remoteConnection = remoteConnection;
this.marshallerFactory = marshallerFactory;
@@ -107,35 +108,33 @@
throw new UnsupportedOperationException();
}
- public void close() throws IOException {
- if (! closed.getAndSet(true)) {
- try {
- remoteConnection.close();
- } finally {
- // other actions here
- for (IntKeyMap.Entry<OutboundClient> entry : outboundClients) {
- final OutboundClient outboundClient = entry.getValue();
- synchronized (outboundClient) {
- IoUtils.safeClose(outboundClient.getRequestHandler());
- }
+ protected void closeAction() throws IOException {
+ try {
+ remoteConnection.close();
+ } finally {
+ // other actions here
+ for (IntKeyMap.Entry<OutboundClient> entry : outboundClients) {
+ final OutboundClient outboundClient = entry.getValue();
+ synchronized (outboundClient) {
+ IoUtils.safeClose(outboundClient.getRequestHandler());
}
- for (IntKeyMap.Entry<InboundClient> entry : inboundClients) {
- final InboundClient inboundClient = entry.getValue();
- synchronized (inboundClient) {
- IoUtils.safeClose(inboundClient.getHandler());
- }
+ }
+ for (IntKeyMap.Entry<InboundClient> entry : inboundClients) {
+ final InboundClient inboundClient = entry.getValue();
+ synchronized (inboundClient) {
+ IoUtils.safeClose(inboundClient.getHandler());
}
- for (IntKeyMap.Entry<OutboundRequest> entry : outboundRequests) {
- final OutboundRequest outboundRequest = entry.getValue();
- synchronized (outboundRequest) {
-
SpiUtils.safeHandleException(outboundRequest.getInboundReplyHandler(), new
IndeterminateOutcomeException("Connection closed"));
- }
+ }
+ for (IntKeyMap.Entry<OutboundRequest> entry : outboundRequests) {
+ final OutboundRequest outboundRequest = entry.getValue();
+ synchronized (outboundRequest) {
+
SpiUtils.safeHandleException(outboundRequest.getInboundReplyHandler(), new
IndeterminateOutcomeException("Connection closed"));
}
- for (IntKeyMap.Entry<InboundRequest> entry : inboundRequests) {
- final InboundRequest inboundRequest = entry.getValue();
- synchronized (inboundRequest) {
- inboundRequest.getCancellable().cancel();
- }
+ }
+ for (IntKeyMap.Entry<InboundRequest> entry : inboundRequests) {
+ final InboundRequest inboundRequest = entry.getValue();
+ synchronized (inboundRequest) {
+ inboundRequest.getCancellable().cancel();
}
}
}
Modified:
remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/remote/RemoteMessageHandler.java
===================================================================
---
remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/remote/RemoteMessageHandler.java 2010-02-28
15:51:38 UTC (rev 5771)
+++
remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/remote/RemoteMessageHandler.java 2010-02-28
21:14:06 UTC (rev 5772)
@@ -38,12 +38,13 @@
import org.jboss.xnio.OptionMap;
import org.jboss.xnio.Pool;
-final class RemoteMessageHandler implements org.jboss.xnio.channels.MessageHandler {
+final class RemoteMessageHandler extends AbstractMessageHandler implements
org.jboss.xnio.channels.MessageHandler {
private final RemoteConnection connection;
private final RemoteConnectionHandler remoteConnectionHandler;
RemoteMessageHandler(final RemoteConnectionHandler remoteConnectionHandler, final
RemoteConnection connection) {
+ super(connection);
this.remoteConnectionHandler = remoteConnectionHandler;
this.connection = connection;
}
@@ -309,12 +310,4 @@
}
}
}
-
- public void handleEof() {
- IoUtils.safeClose(remoteConnectionHandler);
- }
-
- public void handleException(final IOException e) {
- IoUtils.safeClose(remoteConnectionHandler);
- }
}
Modified:
remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/remote/RemoteProtocol.java
===================================================================
---
remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/remote/RemoteProtocol.java 2010-02-28
15:51:38 UTC (rev 5771)
+++
remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/remote/RemoteProtocol.java 2010-02-28
21:14:06 UTC (rev 5772)
@@ -66,6 +66,7 @@
static final byte GREETING_VERSION = 0; // sent by client & server
static final byte GREETING_SASL_MECH = 1; // sent by server
+ static final byte GREETING_ENDPOINT_NAME = 2; // sent by client & server
/**
* Create an instance of the connection provider for the "remote"
protocol.
Modified:
remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/remote/SaslUtils.java
===================================================================
---
remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/remote/SaslUtils.java 2010-02-28
15:51:38 UTC (rev 5771)
+++
remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/remote/SaslUtils.java 2010-02-28
21:14:06 UTC (rev 5772)
@@ -68,15 +68,20 @@
}
private static void addQopList(OptionMap optionMap,
Option<Sequence<SaslQop>> option, Map<String, Object> map, String
propName) {
- final Sequence<SaslQop> seq = optionMap.get(option);
+ final Sequence<SaslQop> value = optionMap.get(option);
+ if (value == null) return;
+ final Sequence<SaslQop> seq = value;
final StringBuilder builder = new StringBuilder();
final Iterator<SaslQop> iterator = seq.iterator();
- while (iterator.hasNext()) {
+ if (!iterator.hasNext()) {
+ return;
+ } else do {
builder.append(iterator.next());
if (iterator.hasNext()) {
builder.append(',');
}
- }
+ } while (iterator.hasNext());
+ map.put(propName, builder.toString());
}
private static final Set<String> SECURE_QOP;
Modified:
remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/remote/ServerAuthenticationHandler.java
===================================================================
---
remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/remote/ServerAuthenticationHandler.java 2010-02-28
15:51:38 UTC (rev 5771)
+++
remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/remote/ServerAuthenticationHandler.java 2010-02-28
21:14:06 UTC (rev 5772)
@@ -34,17 +34,17 @@
import org.jboss.remoting3.spi.ConnectionProviderContext;
import org.jboss.xnio.Buffers;
import org.jboss.xnio.IoUtils;
-import org.jboss.xnio.channels.MessageHandler;
import javax.security.sasl.SaslException;
import javax.security.sasl.SaslServer;
-final class ServerAuthenticationHandler implements MessageHandler {
+final class ServerAuthenticationHandler extends AbstractMessageHandler {
private final RemoteConnection remoteConnection;
private final SaslServer saslServer;
private final ConnectionProviderContext connectionProviderContext;
ServerAuthenticationHandler(final RemoteConnection remoteConnection, final SaslServer
saslServer, final ConnectionProviderContext connectionProviderContext) {
+ super(remoteConnection);
this.saslServer = saslServer;
this.remoteConnection = remoteConnection;
this.connectionProviderContext = connectionProviderContext;
@@ -53,17 +53,20 @@
public void handleMessage(final ByteBuffer buffer) {
switch (buffer.get()) {
case RemoteProtocol.AUTH_RESPONSE: {
+ RemoteConnectionHandler.log.trace("Received SASL response");
final byte[] challenge;
try {
try {
challenge = saslServer.evaluateResponse(Buffers.take(buffer,
buffer.remaining()));
} catch (SaslException e) {
- // todo log it
+ RemoteConnectionHandler.log.trace(e, "Server authentication
failed");
remoteConnection.sendAuthReject("Authentication
failed");
+ remoteConnection.flushBlocking();
return;
}
final boolean complete = saslServer.isComplete();
if (complete) {
+ RemoteConnectionHandler.log.trace("Sending SASL
complete");
remoteConnection.sendAuthMessage(RemoteProtocol.AUTH_COMPLETE,
challenge);
connectionProviderContext.accept(new ConnectionHandlerFactory()
{
public ConnectionHandler createInstance(final
ConnectionHandlerContext connectionContext) {
@@ -80,15 +83,17 @@
}
});
} else {
+ RemoteConnectionHandler.log.trace("Sending subsequent SASL
challenge");
remoteConnection.sendAuthMessage(RemoteProtocol.AUTH_CHALLENGE,
challenge);
}
} catch (IOException e) {
- // todo log it; close channel
+ RemoteConnectionHandler.log.trace(e, "Failed to send auth
message");
IoUtils.safeClose(remoteConnection);
}
+ break;
}
default: {
- // todo log invalid msg
+ RemoteConnectionHandler.log.warn("Server received invalid message on
%s", remoteConnection);
IoUtils.safeClose(remoteConnection);
}
}
Modified:
remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/remote/ServerGreetingHandler.java
===================================================================
---
remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/remote/ServerGreetingHandler.java 2010-02-28
15:51:38 UTC (rev 5771)
+++
remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/remote/ServerGreetingHandler.java 2010-02-28
21:14:06 UTC (rev 5772)
@@ -30,16 +30,16 @@
import org.jboss.remoting3.spi.ConnectionProviderContext;
import org.jboss.xnio.Buffers;
import org.jboss.xnio.IoUtils;
-import org.jboss.xnio.channels.MessageHandler;
-final class ServerGreetingHandler implements MessageHandler {
+final class ServerGreetingHandler extends AbstractMessageHandler {
private final RemoteConnection connection;
private final ConnectionProviderContext connectionProviderContext;
private final Set<String> saslMechs;
private final ServerAuthenticationProvider provider;
private final Map<String, Object> propertyMap;
- public ServerGreetingHandler(final RemoteConnection connection, final
ConnectionProviderContext connectionProviderContext, final Set<String> saslMechs,
final ServerAuthenticationProvider provider, final Map<String, Object> propertyMap)
{
+ ServerGreetingHandler(final RemoteConnection connection, final
ConnectionProviderContext connectionProviderContext, final Set<String> saslMechs,
final ServerAuthenticationProvider provider, final Map<String, Object> propertyMap)
{
+ super(connection);
this.connection = connection;
this.connectionProviderContext = connectionProviderContext;
this.saslMechs = saslMechs;
@@ -71,18 +71,9 @@
return;
}
default: {
- // todo log invalid greeting
+ RemoteConnectionHandler.log.warn("Server received invalid greeting
message");
IoUtils.safeClose(connection);
}
}
}
-
- public void handleEof() {
- IoUtils.safeClose(connection);
- }
-
- public void handleException(final IOException e) {
- // todo log it
- IoUtils.safeClose(connection);
- }
}
Modified:
remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/remote/ServerInitialAuthenticationHandler.java
===================================================================
---
remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/remote/ServerInitialAuthenticationHandler.java 2010-02-28
15:51:38 UTC (rev 5771)
+++
remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/remote/ServerInitialAuthenticationHandler.java 2010-02-28
21:14:06 UTC (rev 5772)
@@ -26,26 +26,27 @@
import java.nio.ByteBuffer;
import java.util.Map;
import java.util.Set;
+import org.jboss.remoting3.RemotingOptions;
import org.jboss.remoting3.security.ServerAuthenticationProvider;
import org.jboss.remoting3.spi.ConnectionProviderContext;
import org.jboss.xnio.Buffers;
import org.jboss.xnio.IoUtils;
-import org.jboss.xnio.channels.MessageHandler;
import javax.security.sasl.Sasl;
import javax.security.sasl.SaslServer;
-final class ServerInitialAuthenticationHandler implements MessageHandler {
+final class ServerInitialAuthenticationHandler extends AbstractMessageHandler {
private final RemoteConnection remoteConnection;
private final Map<String, ?> saslPropertyMap;
- private final Set<String> allowedMechsMap;
+ private final Set<String> allowedMechs;
private final ServerAuthenticationProvider authenticationProvider;
private final ConnectionProviderContext connectionProviderContext;
- ServerInitialAuthenticationHandler(final RemoteConnection remoteConnection, final
Map<String, ?> saslPropertyMap, final Set<String> allowedMechsMap, final
ServerAuthenticationProvider authenticationProvider, final ConnectionProviderContext
connectionProviderContext) {
+ ServerInitialAuthenticationHandler(final RemoteConnection remoteConnection, final
Map<String, ?> saslPropertyMap, final Set<String> allowedMechs, final
ServerAuthenticationProvider authenticationProvider, final ConnectionProviderContext
connectionProviderContext) {
+ super(remoteConnection);
this.remoteConnection = remoteConnection;
this.saslPropertyMap = saslPropertyMap;
- this.allowedMechsMap = allowedMechsMap;
+ this.allowedMechs = allowedMechs;
this.authenticationProvider = authenticationProvider;
this.connectionProviderContext = connectionProviderContext;
}
@@ -56,37 +57,29 @@
try {
// mech name
final String name = Buffers.getModifiedUtf8(buffer);
- if (allowedMechsMap.contains(name)) {
- final SaslServer server = Sasl.createSaslServer(name,
"remote", remoteConnection.getChannel().getLocalAddress().getHostName(),
saslPropertyMap, authenticationProvider.getCallbackHandler());
+ if (allowedMechs.contains(name)) {
+ RemoteConnectionHandler.log.trace("Selected SASL mechanism
%s", name);
+ final String realm =
connectionProviderContext.getEndpointName();
+ final SaslServer server = Sasl.createSaslServer(name,
"remote", realm, saslPropertyMap, authenticationProvider.getCallbackHandler());
remoteConnection.setMessageHandler(new
ServerAuthenticationHandler(remoteConnection, server, connectionProviderContext));
- remoteConnection.sendAuthMessage(RemoteProtocol.AUTH_CHALLENGE,
SaslUtils.EMPTY);
+ RemoteConnectionHandler.log.trace("Sending initial
challenge");
+ remoteConnection.sendAuthMessage(RemoteProtocol.AUTH_CHALLENGE,
server.evaluateResponse(SaslUtils.EMPTY));
return;
} else {
+ RemoteConnectionHandler.log.trace("Rejected invalid SASL
mechanism %s", name);
remoteConnection.sendAuthReject("Invalid mechanism
name");
return;
}
} catch (IOException e) {
IoUtils.safeClose(remoteConnection);
- // todo log it
+ RemoteConnectionHandler.log.trace("Failed to send auth message:
%s", e);
return;
}
}
default: {
- // todo log invalid msg
+ RemoteConnectionHandler.log.warn("Server received invalid auth
request message");
IoUtils.safeClose(remoteConnection);
}
}
}
-
- public void handleEof() {
- try {
- remoteConnection.shutdownReads();
- } catch (IOException e) {
- // todo log it
- }
- }
-
- public void handleException(final IOException e) {
- // todo log it
- }
}
Modified:
remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/remote/ServerOpenListener.java
===================================================================
---
remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/remote/ServerOpenListener.java 2010-02-28
15:51:38 UTC (rev 5771)
+++
remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/remote/ServerOpenListener.java 2010-02-28
21:14:06 UTC (rev 5772)
@@ -63,7 +63,7 @@
final RemoteConnection connection = new
RemoteConnection(connectionProviderContext.getExecutor(), channel, optionMap);
// Calculate available server mechanisms
- final Sequence<String> mechs =
optionMap.get(RemotingOptions.SASL_SERVER_MECHANISMS);
+ final Sequence<String> mechs = optionMap.get(Options.SASL_MECHANISMS);
final Set<String> includes = mechs != null ? new
HashSet<String>(mechs) : null;
final Set<String> serverMechanisms = new LinkedHashSet<String>();
final Map<String, Object> propertyMap =
SaslUtils.createPropertyMap(optionMap);
@@ -79,24 +79,42 @@
// Send server greeting packet...
final ByteBuffer buffer = connection.allocate();
- try {
- // length placeholder
- buffer.putInt(0);
- // version ID
- GreetingUtils.writeByte(buffer, RemoteProtocol.GREETING_VERSION,
RemoteProtocol.VERSION);
- // SASL server mechs
- for (String name : serverMechanisms) {
- GreetingUtils.writeString(buffer, RemoteProtocol.GREETING_SASL_MECH,
name);
+ // length placeholder
+ buffer.putInt(0);
+ // version ID
+ GreetingUtils.writeByte(buffer, RemoteProtocol.GREETING_VERSION,
RemoteProtocol.VERSION);
+ // SASL server mechs
+ for (String name : serverMechanisms) {
+ GreetingUtils.writeString(buffer, RemoteProtocol.GREETING_SASL_MECH, name);
+ RemoteConnectionHandler.log.trace("Offering SASL mechanism %s",
name);
+ }
+ GreetingUtils.writeString(buffer, RemoteProtocol.GREETING_ENDPOINT_NAME,
connectionProviderContext.getEndpointName());
+ // that's it!
+ buffer.flip();
+ buffer.putInt(0, buffer.remaining() - 4);
+ channel.getWriteSetter().set(new
ChannelListener<ConnectedStreamChannel<InetSocketAddress>>() {
+ public void handleEvent(final ConnectedStreamChannel<InetSocketAddress>
channel) {
+ for (;;) {
+ while (buffer.hasRemaining()) {
+ final int res;
+ try {
+ res = channel.write(buffer);
+ } catch (IOException e1) {
+ IoUtils.safeClose(connection);
+ connection.free(buffer);
+ return;
+ }
+ if (res == 0) {
+ channel.resumeWrites();
+ return;
+ }
+ }
+ connection.free(buffer);
+ channel.resumeReads();
+ return;
+ }
}
- // that's it!
- buffer.flip();
- connection.sendBlocking(buffer);
- } catch (Exception e1) {
- // todo log it
- IoUtils.safeClose(connection);
- } finally {
- connection.free(buffer);
- }
+ });
final String authProvider =
optionMap.get(RemotingOptions.AUTHENTICATION_PROVIDER);
if (authProvider == null) {
// todo log no valid auth provider
@@ -108,7 +126,7 @@
IoUtils.safeClose(connection);
}
connection.setMessageHandler(new ServerGreetingHandler(connection,
connectionProviderContext, serverMechanisms, provider, propertyMap));
- // start up the read cycle
- channel.resumeReads();
+ // and send the greeting
+ channel.resumeWrites();
}
}
Modified:
remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/security/SimpleClientCallbackHandler.java
===================================================================
---
remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/security/SimpleClientCallbackHandler.java 2010-02-28
15:51:38 UTC (rev 5771)
+++
remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/security/SimpleClientCallbackHandler.java 2010-02-28
21:14:06 UTC (rev 5772)
@@ -71,12 +71,28 @@
*/
public void handle(final Callback[] callbacks) throws UnsupportedCallbackException {
MAIN: for (Callback callback : callbacks) {
- if (callback instanceof NameCallback && actualUserName != null) {
+ if (callback instanceof NameCallback) {
final NameCallback nameCallback = (NameCallback) callback;
- nameCallback.setName(actualUserName);
- } else if (callback instanceof RealmCallback && actualUserRealm !=
null) {
+ final String defaultName = nameCallback.getDefaultName();
+ log.trace("User name requested; prompt '%s', default is
'%s', ours is '%s'", nameCallback.getPrompt(), defaultName,
actualUserName);
+ if (actualUserName == null) {
+ if (defaultName != null) {
+ nameCallback.setName(defaultName);
+ }
+ } else {
+ nameCallback.setName(actualUserName);
+ }
+ } else if (callback instanceof RealmCallback) {
final RealmCallback realmCallback = (RealmCallback) callback;
- realmCallback.setText(actualUserRealm);
+ final String defaultRealm = realmCallback.getDefaultText();
+ log.trace("Realm requested; prompt '%s', default is
'%s', ours is '%s'", realmCallback.getPrompt(), defaultRealm,
actualUserRealm);
+ if (actualUserRealm == null) {
+ if (defaultRealm != null) {
+ realmCallback.setText(defaultRealm);
+ }
+ } else {
+ realmCallback.setText(actualUserRealm);
+ }
} else if (callback instanceof RealmChoiceCallback && actualUserRealm
!= null) {
final RealmChoiceCallback realmChoiceCallback = (RealmChoiceCallback)
callback;
final String[] choices = realmChoiceCallback.getChoices();
Modified:
remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/spi/AbstractHandleableCloseable.java
===================================================================
---
remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/spi/AbstractHandleableCloseable.java 2010-02-28
15:51:38 UTC (rev 5771)
+++
remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/spi/AbstractHandleableCloseable.java 2010-02-28
21:14:06 UTC (rev 5772)
@@ -23,6 +23,7 @@
package org.jboss.remoting3.spi;
import java.io.IOException;
+import java.io.InterruptedIOException;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.IdentityHashMap;
@@ -49,9 +50,16 @@
private final StackTraceElement[] backtrace;
private final Object closeLock = new Object();
- private boolean closed;
+ private Thread closingThread;
+ private State state = State.OPEN;
private Map<Key, CloseHandler<? super T>> closeHandlers = null;
+ enum State {
+ OPEN,
+ CLOSING,
+ CLOSED,
+ }
+
static {
boolean b = false;
try {
@@ -87,7 +95,7 @@
*/
protected boolean isOpen() {
synchronized (closeLock) {
- return ! closed;
+ return state == State.OPEN;
}
}
@@ -104,12 +112,32 @@
public void close() throws IOException {
final Map<Key, CloseHandler<? super T>> closeHandlers;
synchronized (closeLock) {
- if (closed) {
- return;
+ switch (state) {
+ case OPEN: {
+ state = State.CLOSING;
+ closingThread = Thread.currentThread();
+ closeHandlers = this.closeHandlers;
+ this.closeHandlers = null;
+ break;
+ }
+ case CLOSING: {
+ if (Thread.currentThread() != closingThread) {
+ while (state != State.CLOSED) {
+ try {
+ closeLock.wait();
+ } catch (InterruptedException e) {
+ Thread.currentThread().interrupt();
+ throw new InterruptedIOException("Close
interrupted");
+ }
+ }
+ } else {
+ // reentrant close always goes through unblocked
+ }
+ return;
+ }
+ case CLOSED: return;
+ default: throw new IllegalStateException();
}
- closed = true;
- closeHandlers = this.closeHandlers;
- this.closeHandlers = null;
}
if (closeHandlers != null) {
log.trace("Closed %s", this);
@@ -119,7 +147,15 @@
}
}
}
- closeAction();
+ try {
+ closeAction();
+ } finally {
+ synchronized (closeLock) {
+ state = State.CLOSED;
+ closingThread = null;
+ closeLock.notifyAll();
+ }
+ }
}
/**
@@ -130,7 +166,7 @@
throw new NullPointerException("handler is null");
}
synchronized (closeLock) {
- if (! closed) {
+ if (state == State.OPEN) {
final Key key = new KeyImpl<T>(this);
final Map<Key, CloseHandler<? super T>> closeHandlers =
this.closeHandlers;
if (closeHandlers == null) {
@@ -215,7 +251,7 @@
*/
protected void checkOpen() throws NotOpenException {
synchronized (closeLock) {
- if (closed) {
+ if (state != State.OPEN) {
throw new NotOpenException(toString() + " is not open");
}
}
Modified:
remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/spi/ConnectionProviderContext.java
===================================================================
---
remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/spi/ConnectionProviderContext.java 2010-02-28
15:51:38 UTC (rev 5771)
+++
remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/spi/ConnectionProviderContext.java 2010-02-28
21:14:06 UTC (rev 5772)
@@ -66,4 +66,11 @@
* @return the provider, or {@code null} if none was matched
*/
<T> T getProtocolServiceProvider(ProtocolServiceType<T> serviceType,
String name);
+
+ /**
+ * Get the endpoint's name.
+ *
+ * @return the endpoint name
+ */
+ String getEndpointName();
}
Modified:
remoting3/trunk/jboss-remoting/src/test/java/org/jboss/remoting3/test/RemoteTestCase.java
===================================================================
---
remoting3/trunk/jboss-remoting/src/test/java/org/jboss/remoting3/test/RemoteTestCase.java 2010-02-28
15:51:38 UTC (rev 5771)
+++
remoting3/trunk/jboss-remoting/src/test/java/org/jboss/remoting3/test/RemoteTestCase.java 2010-02-28
21:14:06 UTC (rev 5772)
@@ -37,6 +37,7 @@
import org.jboss.xnio.IoFuture;
import org.jboss.xnio.IoUtils;
import org.jboss.xnio.OptionMap;
+import org.jboss.xnio.Options;
import org.jboss.xnio.Xnio;
import org.jboss.xnio.channels.BoundChannel;
import org.jboss.xnio.channels.ConnectedStreamChannel;
@@ -49,6 +50,7 @@
import javax.security.auth.callback.PasswordCallback;
import javax.security.auth.callback.UnsupportedCallbackException;
import javax.security.sasl.AuthenticationException;
+import javax.security.sasl.AuthorizeCallback;
import javax.security.sasl.RealmCallback;
@Test(suiteName = "Remote tests")
@@ -66,7 +68,11 @@
for (Callback callback : callbacks) {
if (callback instanceof NameCallback) {
final NameCallback nameCallback = (NameCallback)
callback;
- if (!
nameCallback.getName().equals("user")) {
+ final String defaultName =
nameCallback.getDefaultName();
+ if (defaultName != null) {
+ nameCallback.setName(defaultName);
+ }
+ if (!"user".equals(nameCallback.getName()))
{
throw new AuthenticationException("Invalid
user name");
}
} else if (callback instanceof PasswordCallback) {
@@ -74,8 +80,11 @@
passwordCallback.setPassword("password".toCharArray());
} else if (callback instanceof RealmCallback) {
// allow
+ } else if (callback instanceof AuthorizeCallback) {
+ final AuthorizeCallback authorizeCallback =
(AuthorizeCallback) callback;
+
authorizeCallback.setAuthorized(authorizeCallback.getAuthenticationID().equals(authorizeCallback.getAuthorizationID()));
} else {
- throw new UnsupportedCallbackException(callback);
+ throw new UnsupportedCallbackException(callback,
"Callback not supported: " + callback);
}
}
}
@@ -89,14 +98,14 @@
protected Connection getConnection() throws IOException {
final NetworkServerProvider provider =
endpoint.getConnectionProviderInterface("remote", NetworkServerProvider.class);
- final ChannelListener<ConnectedStreamChannel<InetSocketAddress>>
listener =
provider.getServerListener(OptionMap.builder().set(RemotingOptions.AUTHENTICATION_PROVIDER,
"test").getMap());
+ final ChannelListener<ConnectedStreamChannel<InetSocketAddress>>
listener =
provider.getServerListener(OptionMap.builder().set(RemotingOptions.AUTHENTICATION_PROVIDER,
"test").setSequence(Options.SASL_MECHANISMS, "DIGEST-MD5").getMap());
final Xnio xnio = Xnio.getInstance();
try {
- final AcceptingServer<InetSocketAddress, ?, ?> server =
xnio.createSslTcpServer(listener, OptionMap.EMPTY);
-// final AcceptingServer<InetSocketAddress, ?, ?> server =
xnio.createTcpServer(listener, OptionMap.EMPTY);
+// final AcceptingServer<InetSocketAddress, ?, ?> server =
xnio.createSslTcpServer(listener, OptionMap.EMPTY);
+ final AcceptingServer<InetSocketAddress, ?, ?> server =
xnio.createTcpServer(listener, OptionMap.EMPTY);
final IoFuture<? extends BoundChannel<InetSocketAddress>> future
= server.bind(new InetSocketAddress(InetAddress.getByName("127.0.0.1"), 0));
final InetSocketAddress localAddress = future.get().getLocalAddress();
- final Connection connection = endpoint.connect(new URI("remote",
null, localAddress.getAddress().getHostAddress(), localAddress.getPort(), null, null,
null), OptionMap.EMPTY, "user", "realm",
"password".toCharArray()).get();
+ final Connection connection = endpoint.connect(new URI("remote",
null, localAddress.getAddress().getHostAddress(), localAddress.getPort(), null, null,
null), OptionMap.EMPTY, "user", null,
"password".toCharArray()).get();
connection.addCloseHandler(new CloseHandler<Connection>() {
public void handleClose(final Connection closed) {
IoUtils.safeClose(server);
Modified: remoting3/trunk/jboss-remoting/src/test/resources/remoting.properties
===================================================================
--- remoting3/trunk/jboss-remoting/src/test/resources/remoting.properties 2010-02-28
15:51:38 UTC (rev 5771)
+++ remoting3/trunk/jboss-remoting/src/test/resources/remoting.properties 2010-02-28
21:14:06 UTC (rev 5772)
@@ -20,4 +20,4 @@
# 02110-1301 USA, or see the FSF site:
http://www.fsf.org.
#
-#remote.ssl.enable=false
+remote.ssl.enable=false