/* * Copyright 2012-2015, the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.flipkart.phantom.netty.uds; import org.jboss.netty.channel.*; import org.jboss.netty.util.ThreadRenamingRunnable; import org.jboss.netty.util.internal.DeadLockProofWorker; import java.io.PushbackInputStream; import java.net.SocketAddress; import java.util.concurrent.Executor; import static org.jboss.netty.channel.Channels.*; /** * Based on: org.jboss.netty.channel.socket.oio.OioClientSocketPipelineSink * OIO package modified to work for Unix Domain Sockets instead of ServerSocket. * * @author devashishshankar * @version 1.0, 19th April 2013 */ class OioClientSocketPipelineSink extends AbstractChannelSink { private final Executor workerExecutor; OioClientSocketPipelineSink(Executor workerExecutor) { this.workerExecutor = workerExecutor; } public void eventSunk( ChannelPipeline pipeline, ChannelEvent e) throws Exception { OioClientSocketChannel channel = (OioClientSocketChannel) e.getChannel(); ChannelFuture future = e.getFuture(); if (e instanceof ChannelStateEvent) { ChannelStateEvent stateEvent = (ChannelStateEvent) e; ChannelState state = stateEvent.getState(); Object value = stateEvent.getValue(); switch (state) { case OPEN: if (Boolean.FALSE.equals(value)) { OioWorker.close(channel, future); } break; case BOUND: if (value != null) { bind(channel, future, (SocketAddress) value); } else { OioWorker.close(channel, future); } break; case CONNECTED: if (value != null) { connect(channel, future, (SocketAddress) value); } else { OioWorker.close(channel, future); } break; case INTEREST_OPS: OioWorker.setInterestOps(channel, future, ((Integer) value).intValue()); break; } } else if (e instanceof MessageEvent) { OioWorker.write( channel, future, ((MessageEvent) e).getMessage()); } } private void bind( OioClientSocketChannel channel, ChannelFuture future, SocketAddress localAddress) { try { channel.socket.bind(localAddress); future.setSuccess(); fireChannelBound(channel, channel.getLocalAddress()); } catch (Throwable t) { future.setFailure(t); fireExceptionCaught(channel, t); } } private void connect( OioClientSocketChannel channel, ChannelFuture future, SocketAddress remoteAddress) { boolean bound = channel.isBound(); boolean connected = false; boolean workerStarted = false; future.addListener(ChannelFutureListener.CLOSE_ON_FAILURE); try { channel.socket.connect( remoteAddress, channel.getConfig().getConnectTimeoutMillis()); connected = true; // Obtain I/O stream. channel.in = new PushbackInputStream(channel.socket.getInputStream(), 1); channel.out = channel.socket.getOutputStream(); // Fire events. future.setSuccess(); if (!bound) { fireChannelBound(channel, channel.getLocalAddress()); } fireChannelConnected(channel, channel.getRemoteAddress()); // Start the business. DeadLockProofWorker.start( workerExecutor, new ThreadRenamingRunnable( new OioWorker(channel), "Old I/O client worker (" + channel + ')')); workerStarted = true; } catch (Throwable t) { future.setFailure(t); fireExceptionCaught(channel, t); } finally { if (connected && !workerStarted) { OioWorker.close(channel, future); } } } }