package org.sdnplatform.sync.internal.config.bootstrap;
import org.jboss.netty.channel.Channel;
import org.jboss.netty.channel.ChannelHandlerContext;
import org.jboss.netty.channel.ChannelStateEvent;
import org.sdnplatform.sync.IStoreClient;
import org.sdnplatform.sync.Versioned;
import org.sdnplatform.sync.error.AuthException;
import org.sdnplatform.sync.error.ObsoleteVersionException;
import org.sdnplatform.sync.internal.config.AuthScheme;
import org.sdnplatform.sync.internal.config.SyncStoreCCProvider;
import org.sdnplatform.sync.internal.rpc.AbstractRPCChannelHandler;
import org.sdnplatform.sync.internal.rpc.TVersionedValueIterable;
import org.sdnplatform.sync.internal.store.IStorageEngine;
import org.sdnplatform.sync.internal.util.ByteArray;
import org.sdnplatform.sync.internal.util.CryptoUtil;
import org.sdnplatform.sync.thrift.AsyncMessageHeader;
import org.sdnplatform.sync.thrift.ClusterJoinRequestMessage;
import org.sdnplatform.sync.thrift.ClusterJoinResponseMessage;
import org.sdnplatform.sync.thrift.ErrorMessage;
import org.sdnplatform.sync.thrift.HelloMessage;
import org.sdnplatform.sync.thrift.KeyedValues;
import org.sdnplatform.sync.thrift.MessageType;
import org.sdnplatform.sync.thrift.SyncMessage;
import org.sdnplatform.sync.thrift.VersionedValue;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class BootstrapChannelHandler extends AbstractRPCChannelHandler {
protected static final Logger logger =
LoggerFactory.getLogger(BootstrapChannelHandler.class);
private Bootstrap bootstrap;
private Short remoteNodeId;
public BootstrapChannelHandler(Bootstrap bootstrap) {
super();
this.bootstrap = bootstrap;
}
// ****************************
// IdleStateAwareChannelHandler
// ****************************
@Override
public void channelOpen(ChannelHandlerContext ctx,
ChannelStateEvent e) throws Exception {
bootstrap.cg.add(ctx.getChannel());
}
// ******************************************
// AbstractRPCChannelHandler message handlers
// ******************************************
@Override
protected void handleHello(HelloMessage hello, Channel channel) {
remoteNodeId = hello.getNodeId();
org.sdnplatform.sync.thrift.Node n =
new org.sdnplatform.sync.thrift.Node();
n.setHostname(bootstrap.localNode.getHostname());
n.setPort(bootstrap.localNode.getPort());
if (bootstrap.localNode.getNodeId() >= 0)
n.setNodeId(bootstrap.localNode.getNodeId());
if (bootstrap.localNode.getDomainId() >= 0)
n.setDomainId(bootstrap.localNode.getDomainId());
ClusterJoinRequestMessage cjrm = new ClusterJoinRequestMessage();
AsyncMessageHeader header = new AsyncMessageHeader();
header.setTransactionId(bootstrap.transactionId.getAndIncrement());
cjrm.setHeader(header);
cjrm.setNode(n);
SyncMessage bsm =
new SyncMessage(MessageType.CLUSTER_JOIN_REQUEST);
bsm.setClusterJoinRequest(cjrm);
channel.write(bsm);
}
@Override
protected void handleClusterJoinResponse(ClusterJoinResponseMessage response,
Channel channel) {
try {
IStorageEngine<ByteArray, byte[]> store =
bootstrap.syncManager.
getRawStore(SyncStoreCCProvider.SYSTEM_NODE_STORE);
for (KeyedValues kv : response.getNodeStore()) {
Iterable<VersionedValue> tvvi = kv.getValues();
Iterable<Versioned<byte[]>> vs = new TVersionedValueIterable(tvvi);
store.writeSyncValue(new ByteArray(kv.getKey()), vs);
}
IStoreClient<String, String> unsyncStoreClient =
bootstrap.syncManager.
getStoreClient(SyncStoreCCProvider.SYSTEM_UNSYNC_STORE,
String.class, String.class);
if (response.isSetNewNodeId()) {
while (true) {
try {
unsyncStoreClient.put(SyncStoreCCProvider.LOCAL_NODE_ID,
Short.toString(response.
getNewNodeId()));
break;
} catch (ObsoleteVersionException e) {}
}
}
bootstrap.succeeded = true;
} catch (Exception e) {
logger.error("Error processing cluster join response", e);
channel.write(getError(response.getHeader().getTransactionId(), e,
MessageType.CLUSTER_JOIN_RESPONSE));
}
channel.disconnect();
}
@Override
protected void handleError(ErrorMessage error, Channel channel) {
super.handleError(error, channel);
channel.disconnect();
}
// *************************
// AbstractRPCChannelHandler
// *************************
@Override
protected int getTransactionId() {
return bootstrap.transactionId.getAndIncrement();
}
@Override
protected Short getRemoteNodeId() {
return remoteNodeId;
}
@Override
protected Short getLocalNodeId() {
return null;
}
@Override
protected AuthScheme getAuthScheme() {
return bootstrap.authScheme;
}
@Override
protected byte[] getSharedSecret() throws AuthException {
try {
return CryptoUtil.getSharedSecret(bootstrap.keyStorePath,
bootstrap.keyStorePassword);
} catch (Exception e) {
throw new AuthException("Could not read challenge/response " +
"shared secret from key store " +
bootstrap.keyStorePath, e);
}
}}