All Downloads are FREE. Search and download functionalities are using the official Maven repository.

jnr.unixsocket.UnixDatagramSocket Maven / Gradle / Ivy

/*
 * Copyright (C) 2016 Fritz Elfert
 * 
 * This file is part of the JNR project.
 *
 * 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 jnr.unixsocket;

import java.io.IOException;
import java.net.InetAddress;
import java.net.SocketAddress;
import java.net.SocketException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.nio.channels.DatagramChannel;
import java.nio.channels.UnsupportedAddressTypeException;
import java.util.concurrent.atomic.AtomicBoolean;

/**
 * A SOCK_DGRAM variant of an AF_UNIX socket.
 * This specializaton of DatagramSocket delegates
 * most of it's funtionality to the corresponding
 * UnixDatagramChannel.
 */
public class UnixDatagramSocket extends DatagramSocket {

    private final UnixDatagramChannel chan;
    private final AtomicBoolean closed = new AtomicBoolean(false);

    /**
     * Constructs a new instance.
     * @param channel The channel to use.
     * @throws SocketException if the socket could not be created.
     */
    UnixDatagramSocket(final UnixDatagramChannel channel) throws SocketException {
        chan = channel;
    }


    /**
     * Constructs a new unbound instance.
     * @throws SocketException if the socket could not be created.
     */
    public UnixDatagramSocket() throws SocketException {
        chan = null;
    }

    /**
     * Binds this UnixDatagramSocket to a specific AF_UNIX address.
     * 

* If the address is {@code null}, then on Linux, an autobind will be performed, * which will bind this socket in Linux' abstract namespace on a unique path, chosen by * the system. On all other platforms, A temporary path in the regular filesystem will be chosen. *

* @param local The {@link UnixSocketAddress} to bind to. * @throws SocketException if any error happens during the bind, or if the * socket is already bound. * @throws UnsupportedAddressTypeException if addr is a SocketAddress subclass * not supported by this socket. */ @Override public void bind(final SocketAddress local) throws SocketException { if (null != chan) { if (isClosed()) { throw new SocketException("Socket is closed"); } if (isBound()) { throw new SocketException("already bound"); } try { chan.bind(local); } catch (IOException e) { throw (SocketException)new SocketException().initCause(e); } } } @Override public synchronized void disconnect() { if (isClosed()) { return; } if (null != chan) { try { chan.disconnect(); } catch (IOException e) { ignore(); } } } @Override public synchronized void close() { if (null != chan && closed.compareAndSet(false, true)) { try { chan.close(); } catch (IOException e) { ignore(); } } } @Override public void connect(SocketAddress addr) throws SocketException { try { chan.connect(addr); } catch (IOException e) { throw (SocketException)new SocketException().initCause(e); } } @Override public void connect(InetAddress addr, int port) { throw new UnsupportedOperationException("connect(InetAddress, int) is not supported"); } @Override public DatagramChannel getChannel() { return chan; } /** * Returns the address to which this socket is connected (NOT implemented). * Since AF_UNIX sockets can not have an InetAddress, this returns always {@code null}. * Use {@link #getRemoteSocketAddress} instead, which always returns a {@link UnixSocketAddress}. * @return {@code null} always. */ @Override public InetAddress getInetAddress() { return null; } /** * Returns the address of the endpoint this socket is bound to. * * @return a {@code SocketAddress} representing the local endpoint of this * socket, or {@code null} if it is closed or not bound. * A non-null return value is always of type {@link UnixSocketAddress} * @see #bind(SocketAddress) */ @Override public SocketAddress getLocalSocketAddress() { if (isClosed()) { return null; } if (null == chan) { return null; } return chan.getLocalSocketAddress(); } /** * Returns the address of the endpoint this socket is connected to, or * {@code null} if it is unconnected. * * @return a {@code SocketAddress} representing the remote * endpoint of this socket, or {@code null} if it is * not connected. * A non-null return value is always of type {@link UnixSocketAddress} */ @Override public SocketAddress getRemoteSocketAddress() { if (!isConnected()) { return null; } return chan.getRemoteSocketAddress(); } @Override public boolean isBound() { if (null == chan) { return false; } return chan.isBound(); } @Override public boolean isClosed() { if (null == chan) { return false; } return closed.get(); } @Override public boolean isConnected() { if (null == chan) { return false; } return chan.isConnected(); } /** * Retrieves the credentials for this UNIX socket. Clients calling this * method will receive the server's credentials, and servers will receive * the client's credentials. User ID, group ID, and PID are supplied. * * See man unix 7; SCM_CREDENTIALS * * @throws UnsupportedOperationException if the underlying socket library * doesn't support the SO_PEERCRED option * @throws SocketException if fetching the socket option failed. * * @return the credentials of the remote; null if not connected */ public final Credentials getCredentials() throws SocketException { if (!chan.isConnected()) { return null; } try { return chan.getOption(UnixSocketOptions.SO_PEERCRED); } catch (IOException e) { throw (SocketException)new SocketException().initCause(e); } } @Override public int getReceiveBufferSize() throws SocketException { try { return chan.getOption(UnixSocketOptions.SO_RCVBUF).intValue(); } catch (IOException e) { throw (SocketException)new SocketException().initCause(e); } } @Override public int getSendBufferSize() throws SocketException { try { return chan.getOption(UnixSocketOptions.SO_SNDBUF).intValue(); } catch (IOException e) { throw (SocketException)new SocketException().initCause(e); } } @Override public int getSoTimeout() throws SocketException { try { return chan.getOption(UnixSocketOptions.SO_RCVTIMEO).intValue(); } catch (IOException e) { throw (SocketException)new SocketException().initCause(e); } } @Override public void setReceiveBufferSize(int size) throws SocketException { try { chan.setOption(UnixSocketOptions.SO_RCVBUF, Integer.valueOf(size)); } catch (IOException e) { throw (SocketException)new SocketException().initCause(e); } } @Override public void setSendBufferSize(int size) throws SocketException { try { chan.setOption(UnixSocketOptions.SO_SNDBUF, Integer.valueOf(size)); } catch (IOException e) { throw (SocketException)new SocketException().initCause(e); } } @Override public void setSoTimeout(int timeout) throws SocketException { try { chan.setOption(UnixSocketOptions.SO_RCVTIMEO, Integer.valueOf(timeout)); } catch (IOException e) { throw (SocketException)new SocketException().initCause(e); } } /** * Sends a datagram packet from this socket (NOT implemented). * Unfortunately, {@link java.net.DatagramPacket} is final and can not deal * with AF_UNIX addresses. Therefore, this functionality was omitted. * @see java.net.DatagramPacket * @see java.net.DatagramSocket#send * @throws UnsupportedOperationException always. */ @Override public void send(DatagramPacket p) throws IOException { throw new UnsupportedOperationException("sending DatagramPackets is not supported"); } /** * Receives a datagram packet from this socket (NOT implemented). * Unfortunately, {@link java.net.DatagramPacket} is final and can not deal * with AF_UNIX addresses. Therefore, this functionality was omitted. * @see java.net.DatagramPacket * @see java.net.DatagramSocket#receive * @throws UnsupportedOperationException always. */ @Override public synchronized void receive(DatagramPacket p) throws IOException { throw new UnsupportedOperationException("receiving DatagramPackets is not supported"); } private void ignore() { } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy