package divconq.ctp; import io.netty.bootstrap.Bootstrap; import io.netty.channel.ChannelInitializer; import io.netty.channel.EventLoopGroup; import io.netty.channel.socket.SocketChannel; import io.netty.channel.socket.nio.NioSocketChannel; import divconq.ctp.CtpAdapter; import divconq.ctp.CtpCommand; import divconq.ctp.ICommandHandler; import divconq.ctp.net.CtpHandler; import divconq.ctp.cmd.EngageCommand; import divconq.hub.Hub; import divconq.lang.op.FuncCallback; import divconq.lang.op.OperationCallback; import divconq.struct.RecordStruct; import divconq.work.IWork; import divconq.work.Task; import divconq.work.TaskRun; abstract public class CtpClient implements ICommandHandler { protected CtpAdapter adapter = null; protected RecordStruct startRecord = null; public void sendCommand(CtpCommand cmd) { try { this.adapter.sendCommand(cmd); } catch (Exception x) { System.out.println("ctp client send error: " + x); } } // when using this be sure to issue "read()" in callback public void sendCommand(CtpCommand cmd, FuncCallback<RecordStruct> cb) { try { this.adapter.sendCommand(cmd, cb); } catch (Exception x) { System.out.println("ctp client send error: " + x); } } public void read() { this.adapter.read(); } public void connect(String host, int port, OperationCallback connCallback) { this.adapter = new CtpAdapter(); // TODO maybe from session one day? // OperationContext.get().getSession().allocateCtpAdapter(); this.adapter.setHandler(this); EventLoopGroup el = Hub.instance.getEventLoopGroup(); Bootstrap cb = new Bootstrap() .group(el) .channel(NioSocketChannel.class) .handler(new ChannelInitializer<SocketChannel>() { @Override public void initChannel(SocketChannel ch) throws Exception { ch.pipeline().addLast( //new SslHandler(SslContextFactory.getClientEngine()), // TODO use surface context, not bus // TODO put Zlib encoding directly into CtpHandler so "read" works better //new JdkZlibEncoder(ZlibWrapper.ZLIB), //new JdkZlibDecoder(ZlibWrapper.ZLIB), //new LoggingHandler(LogLevel.INFO), new CtpHandler(CtpClient.this.adapter, false)); } }); // Start the client. try { cb.connect(host, port).sync(); } catch (InterruptedException x) { System.out.println("Could not connect to Ctp Server"); connCallback.error("Unable to connect: " + x); connCallback.callback(); return; } System.out.println("Ctp Client - Connected"); EngageCommand cmd = new EngageCommand(); cmd.setBody(this.startRecord); this.startRecord = null; //System.out.println("Ctp Client - Init Sent"); Task alive = new Task().withWork(new IWork() { @Override public void run(TaskRun trun) { //System.out.println("Ctp Client - Active: " + chx.isActive()); try { CtpClient.this.adapter.sendCommand(CtpCommand.ALIVE); } catch (Exception x) { System.out.println("Ctp-F Client error: " + x); } trun.complete(); } }); this.sendCommand(cmd, new FuncCallback<RecordStruct>() { @Override public void callback() { if (!this.hasErrors()) Hub.instance.getScheduler().runEvery(alive, 30); // we are willing to process more messages adapter.read(); // if errors then caller should close connCallback.complete(); } }); } }