package com.hwlcn.ldap.ldap.sdk; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.TimeUnit; import com.hwlcn.ldap.asn1.ASN1OctetString; import com.hwlcn.ldap.ldap.protocol.BindRequestProtocolOp; import com.hwlcn.ldap.ldap.protocol.LDAPMessage; import com.hwlcn.ldap.ldap.protocol.LDAPResponse; import com.hwlcn.core.annotation.Extensible; import com.hwlcn.core.annotation.InternalUseOnly; import com.hwlcn.core.annotation.ThreadSafety; import com.hwlcn.ldap.util.ThreadSafetyLevel; import static com.hwlcn.ldap.ldap.sdk.LDAPMessages.*; import static com.hwlcn.ldap.util.Debug.*; import static com.hwlcn.ldap.util.StaticUtils.*; @Extensible() @ThreadSafety(level=ThreadSafetyLevel.NOT_THREADSAFE) public abstract class SASLBindRequest extends BindRequest implements ResponseAcceptor { protected static final byte CRED_TYPE_SASL = (byte) 0xA3; private static final long serialVersionUID = -5842126553864908312L; private int messageID; private final LinkedBlockingQueue<LDAPResponse> responseQueue; protected SASLBindRequest(final Control[] controls) { super(controls); messageID = -1; responseQueue = new LinkedBlockingQueue<LDAPResponse>(); } @Override() public String getBindType() { return getSASLMechanismName(); } public abstract String getSASLMechanismName(); @Override() public int getLastMessageID() { return messageID; } protected final BindResult sendBindRequest(final LDAPConnection connection, final String bindDN, final ASN1OctetString saslCredentials, final Control[] controls, final long timeoutMillis) throws LDAPException { if (messageID == -1) { messageID = connection.nextMessageID(); } final BindRequestProtocolOp protocolOp = new BindRequestProtocolOp(bindDN, getSASLMechanismName(), saslCredentials); final LDAPMessage requestMessage = new LDAPMessage(messageID, protocolOp, controls); return sendMessage(connection, requestMessage, timeoutMillis); } protected final BindResult sendMessage(final LDAPConnection connection, final LDAPMessage requestMessage, final long timeoutMillis) throws LDAPException { if (connection.synchronousMode()) { return sendMessageSync(connection, requestMessage, timeoutMillis); } final int msgID = requestMessage.getMessageID(); connection.registerResponseAcceptor(msgID, this); try { final long requestTime = System.nanoTime(); connection.getConnectionStatistics().incrementNumBindRequests(); connection.sendMessage(requestMessage); final LDAPResponse response; try { if (timeoutMillis > 0) { response = responseQueue.poll(timeoutMillis, TimeUnit.MILLISECONDS); } else { response = responseQueue.take(); } } catch (InterruptedException ie) { debugException(ie); throw new LDAPException(ResultCode.LOCAL_ERROR, ERR_BIND_INTERRUPTED.get(connection.getHostPort()), ie); } return handleResponse(connection, response, requestTime); } finally { connection.deregisterResponseAcceptor(msgID); } } private BindResult sendMessageSync(final LDAPConnection connection, final LDAPMessage requestMessage, final long timeoutMillis) throws LDAPException { try { connection.getConnectionInternals(true).getSocket().setSoTimeout( (int) timeoutMillis); } catch (Exception e) { debugException(e); } final int msgID = requestMessage.getMessageID(); final long requestTime = System.nanoTime(); connection.getConnectionStatistics().incrementNumBindRequests(); connection.sendMessage(requestMessage); while (true) { final LDAPResponse response = connection.readResponse(messageID); if (response instanceof IntermediateResponse) { final IntermediateResponseListener listener = getIntermediateResponseListener(); if (listener != null) { listener.intermediateResponseReturned( (IntermediateResponse) response); } } else { return handleResponse(connection, response, requestTime); } } } private BindResult handleResponse(final LDAPConnection connection, final LDAPResponse response, final long requestTime) throws LDAPException { if (response == null) { final long waitTime = nanosToMillis(System.nanoTime() - requestTime); throw new LDAPException(ResultCode.TIMEOUT, ERR_BIND_CLIENT_TIMEOUT.get(waitTime, connection.getHostPort())); } if (response instanceof ConnectionClosedResponse) { final ConnectionClosedResponse ccr = (ConnectionClosedResponse) response; final String message = ccr.getMessage(); if (message == null) { throw new LDAPException(ccr.getResultCode(), ERR_CONN_CLOSED_WAITING_FOR_BIND_RESPONSE.get( connection.getHostPort(), toString())); } else { throw new LDAPException(ccr.getResultCode(), ERR_CONN_CLOSED_WAITING_FOR_BIND_RESPONSE_WITH_MESSAGE.get( connection.getHostPort(), toString(), message)); } } connection.getConnectionStatistics().incrementNumBindResponses( System.nanoTime() - requestTime); return (BindResult) response; } @InternalUseOnly() public final void responseReceived(final LDAPResponse response) throws LDAPException { try { responseQueue.put(response); } catch (Exception e) { debugException(e); throw new LDAPException(ResultCode.LOCAL_ERROR, ERR_EXCEPTION_HANDLING_RESPONSE.get(getExceptionMessage(e)), e); } } }