package com.limegroup.gnutella.handshaking;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.Channel;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
/** Outlines all the states an asynchronous handshake can be in. */
abstract class HandshakeState {
/**
* Returns a new set of HandshakeStates for doing an asynchronous incoming handshake.
*
* @param support The HandshakeSupport supporter that'll keep track of what we're doing.
* @param responder The responder to use when we write a response.
* @return
*/
static List /* of HandshakeState */ getIncomingHandshakeStates(HandshakeSupport support,
HandshakeResponder responder) {
List list = new ArrayList(3);
list.add(new ReadHandshakeState.ReadRequestState(support));
list.add(new WriteHandshakeState.WriteResponseState(support, responder, false));
list.add(new ReadHandshakeState.ReadResponseState(support));
return list;
}
/**
* Returns a new set of HandshakeStates for doing an asynchronous outgoing handshake.
*
* @param support The HandshakeSupport supporter that'll keep track of what we're doing.
* @param request The initial set of request headers to send.
* @param responder The responder to use when we write a response.
* @return
*/
static List /* of HandshakeState */ getOutgoingHandshakeStates(HandshakeSupport support,
Properties request,
HandshakeResponder responder) {
List list = new ArrayList(3);
list.add(new WriteHandshakeState.WriteRequestState(support, request));
list.add(new ReadHandshakeState.ReadResponseState(support));
list.add(new WriteHandshakeState.WriteResponseState(support, responder, true));
return list;
}
/** The HandshakeSupport supporter. */
protected HandshakeSupport support;
/** Constructs a new HandshakeState for reading (or writing) with the given supporter. */
HandshakeState(HandshakeSupport support) {
this.support = support;
}
/** Determines if this HandshakeState is for writing. */
abstract boolean isWriting();
/** Determines if this HandshakeState is for reading. */
abstract boolean isReading();
/**
* Processes this HandshakeState. If this returns true, the state requires further processing.
* This should be called repeatedly until it returns false, at which point the next state should
* be used.
*
* The given Channel must be a ReadableByteChannel if it is for reading or a
* WritableByteChannel if it is for writing.
*
* The given ByteBuffer should be used as scratch space for writing or reading.
*/
abstract boolean process(Channel channel, ByteBuffer buffer) throws IOException;
}