/* * 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.channel.socket.DatagramChannel; import org.jboss.netty.channel.socket.DatagramChannelConfig; import org.jboss.netty.channel.socket.DefaultDatagramChannelConfig; import java.io.IOException; import java.net.*; import static org.jboss.netty.channel.Channels.fireChannelOpen; /** * Based on: org.jboss.netty.channel.socket.oio.OioDatagramChannel * OIO package modified to work for Unix Domain Sockets instead of ServerSocket. * * @author devashishshankar * @version 1.0, 19th April 2013 */ final class OioDatagramChannel extends AbstractChannel implements DatagramChannel { final MulticastSocket socket; final Object interestOpsLock = new Object(); private final DatagramChannelConfig config; volatile Thread workerThread; private volatile InetSocketAddress localAddress; volatile InetSocketAddress remoteAddress; OioDatagramChannel( ChannelFactory factory, ChannelPipeline pipeline, ChannelSink sink) { super(null, factory, pipeline, sink); try { socket = new MulticastSocket(null); } catch (IOException e) { throw new ChannelException("Failed to open a datagram socket.", e); } try { socket.setSoTimeout(10); socket.setBroadcast(false); } catch (SocketException e) { throw new ChannelException( "Failed to configure the datagram socket timeout.", e); } config = new DefaultDatagramChannelConfig(socket); fireChannelOpen(this); } public DatagramChannelConfig getConfig() { return config; } public InetSocketAddress getLocalAddress() { InetSocketAddress localAddress = this.localAddress; if (localAddress == null) { try { this.localAddress = localAddress = (InetSocketAddress) socket.getLocalSocketAddress(); } catch (Throwable t) { // Sometimes fails on a closed socket in Windows. return null; } } return localAddress; } public InetSocketAddress getRemoteAddress() { InetSocketAddress remoteAddress = this.remoteAddress; if (remoteAddress == null) { try { this.remoteAddress = remoteAddress = (InetSocketAddress) socket.getRemoteSocketAddress(); } catch (Throwable t) { // Sometimes fails on a closed socket in Windows. return null; } } return remoteAddress; } public boolean isBound() { return isOpen() && socket.isBound(); } public boolean isConnected() { return isOpen() && socket.isConnected(); } @Override protected boolean setClosed() { return super.setClosed(); } @Override protected void setInterestOpsNow(int interestOps) { super.setInterestOpsNow(interestOps); } @Override public ChannelFuture write(Object message, SocketAddress remoteAddress) { if (remoteAddress == null || remoteAddress.equals(getRemoteAddress())) { return super.write(message, null); } else { return super.write(message, remoteAddress); } } public void joinGroup(InetAddress multicastAddress) { ensureBound(); try { socket.joinGroup(multicastAddress); } catch (IOException e) { throw new ChannelException(e); } } public void joinGroup( InetSocketAddress multicastAddress, NetworkInterface networkInterface) { ensureBound(); try { socket.joinGroup(multicastAddress, networkInterface); } catch (IOException e) { throw new ChannelException(e); } } private void ensureBound() { if (!isBound()) { throw new IllegalStateException( DatagramChannel.class.getName() + " must be bound to join a group."); } } public void leaveGroup(InetAddress multicastAddress) { try { socket.leaveGroup(multicastAddress); } catch (IOException e) { throw new ChannelException(e); } } public void leaveGroup( InetSocketAddress multicastAddress, NetworkInterface networkInterface) { try { socket.leaveGroup(multicastAddress, networkInterface); } catch (IOException e) { throw new ChannelException(e); } } }