Package pushy.net

Source Code of pushy.net.RemoteSocket

/*
* Copyright (c) 2009, 2011 Andrew Wilkins <axwalk@gmail.com>
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/

package pushy.net;

import java.io.IOException;
import java.io.InputStream;
import java.net.SocketAddress;
import java.net.SocketException;
import java.net.InetSocketAddress;
import java.net.InetAddress;

import pushy.PushyObject;
import pushy.Client;
import pushy.modules.SocketModule;
import pushy.modules.StructModule;

public class RemoteSocket extends java.net.Socket
{
    private Client client;
    private PushyObject object;
    private PushyObject accept;
    private PushyObject getsockopt = null;
    private PushyObject setsockopt = null;
    private PushyObject gettimeout = null;
    private PushyObject settimeout = null;
    private boolean bound = false;
    private boolean connected = false;
    private boolean isInputShutdown = false;
    private boolean isOutputShutdown = false;
    private InputStream inputStream = null;

    public RemoteSocket(Client client, PushyObject object)
    {
        this.client = client;
        this.object = object;
        accept = (PushyObject)object.__getattr__("accept");
    }

    /**
     * Bind the socket to an (Inet)SocketAddress.
     *
     * Only AF_INET/AF_INET6 families are supported.
     */
    public void bind(SocketAddress bindpoint) throws IOException
    {
        // Check/set bindpoint (address).
        if (bindpoint == null)
        {
            bindpoint =
                new InetSocketAddress(
                    InetAddress.getByAddress(new byte[]{127, 0, 0, 1}), 0);
        }
        else
        {
            if (!(bindpoint instanceof InetSocketAddress))
                throw new IllegalArgumentException("Unsupported address type");
        }

        InetSocketAddress socketAddress = (InetSocketAddress)bindpoint;
        InetAddress address = socketAddress.getAddress();

        // Call the bind() method.
        PushyObject bindMethod = (PushyObject)object.__getattr__("bind");
        try {
            bindMethod.__call__(new Object[]{
                new Object[]{
                    address.getHostAddress(),
                    new Integer(socketAddress.getPort())
            }});
            bound = true;
        } catch (RuntimeException e) {
            // Socket.bind() throws an IOException if it fails.
            SocketException se = new SocketException();
            se.initCause(e);
            throw se;
        }
    }

    public boolean isConnected()
    {
        return connected;
    }

    public synchronized boolean isBound()
    {
        return bound;
    }

    public synchronized boolean isClosed()
    {
        return object == null;
    }

    public synchronized void close() throws IOException
    {
        if (!isClosed())
        {
            ((PushyObject)object.__getattr__("close")).__call__();
            if (inputStream != null)
                inputStream.close();
            object = null;
            bound = false;
            connected = false;
            isInputShutdown = true;
            isOutputShutdown = true;
            inputStream = null;
        }
    }

    public synchronized int getLocalPort()
    {
        if (!isClosed())
        {
            PushyObject getsockname =
                (PushyObject)object.__getattr__("getsockname");
            Object[] address = (Object[])getsockname.__call__();
            return ((Number)address[1]).intValue();
        }
        return -1; // TODO check if this is what "real" Java does.
    }

    /**
     * Get the peer's address.
     */
    public synchronized SocketAddress getRemoteSocketAddress()
    {
        if (!isClosed())
        {
            PushyObject getpeername =
                (PushyObject)object.__getattr__("getpeername");
            Object[] address = (Object[])getpeername.__call__();
            if (address.length == 2)
            {
                String host = (String)address[0];
                int port = ((Integer)address[1]).intValue();
                return InetSocketAddress.createUnresolved(host, port);
            }
            else if (address.length == 4)
            {
                String host = (String)address[0];
                int port = ((Integer)address[1]).intValue();
                int scope = ((Integer)address[3]).intValue();
                return InetSocketAddress.createUnresolved(
                            host + "%" + scope, port);
            }
            else
            {
                throw new RuntimeException("Unexpected result: " + address);
            }
        }
        return null;
    }

    public void listen(int backlog)
    {
        PushyObject listen = (PushyObject)object.__getattr__("listen");
        listen.__call__(new Object[]{new Integer(backlog)});
    }

    public RemoteSocket accept()
    {
        Object[] result = (Object[])accept.__call__();
        RemoteSocket socket = new RemoteSocket(client, (PushyObject)result[0]);
        socket.connected = true;
        return socket;
    }

    public synchronized void shutdownInput() throws IOException
    {
        if (!isConnected())
            throw new SocketException("Socket is not connected");
        if (!isInputShutdown)
        {
            SocketModule module = (SocketModule)client.getModule("socket");
            PushyObject shutdown = (PushyObject)object.__getattr__("shutdown");
            Object SHUT_WR = module.__getattr__("SHUT_WR");
            shutdown.__call__(new Object[]{SHUT_WR});
            if (inputStream != null)
                inputStream.close();
            inputStream = null;
            isInputShutdown = true;
        }
    }

    public synchronized void shutdownOutput() throws IOException
    {
        if (!isConnected())
            throw new SocketException("Socket is not connected");
        if (!isOutputShutdown)
        {
            SocketModule module = (SocketModule)client.getModule("socket");
            PushyObject shutdown = (PushyObject)object.__getattr__("shutdown");
            Object SHUT_WR = module.__getattr__("SHUT_RD");
            shutdown.__call__(new Object[]{SHUT_WR});
            isOutputShutdown = true;
        }
    }

    public synchronized InputStream getInputStream() throws IOException
    {
        if (!isConnected())
            throw new SocketException("Socket is not connected");
        if (!isInputShutdown)
        {
            if (inputStream == null)
                inputStream = new RemoteSocketInputStream(object);
            return inputStream;
        }
        else
        {
            throw new SocketException("Socket input is shutdown");
        }
    }

    public boolean isInputShutdown()
    {
        return isInputShutdown;
    }

    public boolean isOutputShutdown()
    {
        return isOutputShutdown;
    }

    ///////////////////////////////////////////////////////////////////////////
    // Socket options
    ///////////////////////////////////////////////////////////////////////////

    public boolean getKeepAlive()
    {
        return getsockopt(SocketModule.SOL_SOCKET,
                          SocketModule.SO_KEEPALIVE) == 1;
    }

    public void setKeepAlive(boolean on)
    {
        setsockopt(SocketModule.SOL_SOCKET, SocketModule.SO_KEEPALIVE,
                   new Integer(on ? 1 : 0));
    }

    public boolean getOOBInline()
    {
        return getsockopt(SocketModule.SOL_SOCKET,
                          SocketModule.SO_OOBINLINE) == 1;
    }

    public void setOOBInline(boolean on)
    {
        setsockopt(SocketModule.SOL_SOCKET, SocketModule.SO_OOBINLINE,
                   new Integer(on ? 1 : 0));
    }

    public int getReceiveBufferSize()
    {
        return getsockopt(SocketModule.SOL_SOCKET, SocketModule.SO_RCVBUF);
    }

    public void setReceiveBufferSize(int size)
    {
        setsockopt(SocketModule.SOL_SOCKET, SocketModule.SO_RCVBUF,
                   new Integer(size));
    }

    public int getSendBufferSize()
    {
        return getsockopt(SocketModule.SOL_SOCKET, SocketModule.SO_SNDBUF);
    }

    public void setSendBufferSize(int size)
    {
        setsockopt(SocketModule.SOL_SOCKET, SocketModule.SO_SNDBUF,
                   new Integer(size));
    }

    public boolean getReuseAddress()
    {
        return getsockopt(SocketModule.SOL_SOCKET,
                          SocketModule.SO_REUSEADDR) == 1;
    }

    public void setReuseAddress(boolean on)
    {
        setsockopt(SocketModule.SOL_SOCKET, SocketModule.SO_REUSEADDR,
                   new Integer(on ? 1 : 0));
    }

    public int getSoTimeout()
    {
        if (gettimeout == null) {
            synchronized (this) {
                if (gettimeout == null)
                    gettimeout = (PushyObject)object.__getattr__("gettimeout");
            }
        }
        Object result = gettimeout.__call__();
        if (result == null)
            return 0;
        return (int)(((Number)result).doubleValue() * 1000);
    }

    public void setSoTimeout(int timeout_ms) throws SocketException
    {
        if (settimeout == null) {
            synchronized (this) {
                if (settimeout == null)
                    settimeout = (PushyObject)object.__getattr__("settimeout");
            }
        }
        if (timeout_ms == 0) {
            settimeout.__call__(new Object[]{null});
        } else {
            double timeout_sec = timeout_ms / 1000.0d;
            try {
                settimeout.__call__(new Object[]{new Double(timeout_sec)});
            } catch (pushy.internal.RemoteException e) {
                SocketException e_ = new SocketException(e.getMessage());
                e_.initCause(e);
                throw e_;
            }
        }
    }

    public int getSoLinger()
    {
        StructModule struct_ = (StructModule)client.getModule("struct");
        String result = getsockopt(SocketModule.SOL_SOCKET,
                                   SocketModule.SO_LINGER,
                                   struct_.calcsize("ii"));
        Object[] unpacked = struct_.unpack("ii", result);
        if (unpacked[0].equals(new Integer(0)))
            return -1;
        return ((Number)unpacked[1]).intValue();
    }

    public void setSoLinger(boolean on, int linger)
    {
        StructModule struct_ = (StructModule)client.getModule("struct");
        setsockopt(SocketModule.SOL_SOCKET, SocketModule.SO_LINGER,
            struct_.pack("ii", new Object[]{
                new Integer(on ? 1 : 0), new Integer(linger)}));
    }

    public boolean getTcpNoDelay()
    {
        return getsockopt(SocketModule.IPPROTO_TCP,
                          SocketModule.TCP_NODELAY) == 1;
    }

    public void setTcpNoDelay(boolean on)
    {
        setsockopt(SocketModule.IPPROTO_TCP, SocketModule.TCP_NODELAY,
                   new Integer(on ? 1 : 0));
    }

    public void setTrafficClass(int tos)
    {
        setsockopt(SocketModule.IPPROTO_IP, SocketModule.IP_TOS,
                   new Integer(tos));
    }

    public int getTrafficClass()
    {
        return getsockopt(SocketModule.IPPROTO_IP, SocketModule.IP_TOS);
    }

    private int getsockopt(SocketModule.Protocol level_,
                           SocketModule.SocketOption option_)
    {
        if (getsockopt == null) {
            synchronized (this) {
                if (getsockopt == null)
                    getsockopt = (PushyObject)object.__getattr__("getsockopt");
            }
        }
        SocketModule module = (SocketModule)client.getModule("socket");
        Integer level = module.getConstant(level_);
        Integer option = module.getConstant(option_);
        Object result = getsockopt.__call__(new Object[] {level, option});
        return ((Number)result).intValue();
    }

    /**
     * socket.getsockopt.
     */
    private String getsockopt(SocketModule.Protocol level_,
                              SocketModule.SocketOption option_,
                              int buflen)
    {
        if (getsockopt == null) {
            synchronized (this) {
                if (getsockopt == null)
                    getsockopt = (PushyObject)object.__getattr__("getsockopt");
            }
        }
        SocketModule module = (SocketModule)client.getModule("socket");
        Integer level = module.getConstant(level_);
        Integer option = module.getConstant(option_);
        Object result = getsockopt.__call__(
            new Object[]{level, option, new Integer(buflen)});
        return (String)result;
    }

    /**
     * socket.setsockopt.
     */
    private void
    setsockopt(SocketModule.Protocol level_,
               SocketModule.SocketOption option_, Object value)
    {
        if (setsockopt == null) {
            synchronized (this) {
                if (setsockopt == null)
                    setsockopt = (PushyObject)object.__getattr__("setsockopt");
            }
        }
        SocketModule module = (SocketModule)client.getModule("socket");
        Integer level = module.getConstant(level_);
        Integer option = module.getConstant(option_);
        setsockopt.__call__(new Object[] {level, option, value});
    }
}
TOP

Related Classes of pushy.net.RemoteSocket

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.