de.sciss.net
Class OSCServer

java.lang.Object
  extended by de.sciss.net.OSCServer
All Implemented Interfaces:
OSCBidi, OSCChannel

public abstract class OSCServer
extends Object
implements OSCBidi

This class dynamically groups together a transmitters and receivers, allowing bidirectional OSC communication from the perspective of a server. It simplifies the need to use several objects by uniting their functionality, and by automatically establishing child connections.

In UDP mode, simply one receiver and transmitter are handling all the communication. In TCP mode, a ServerSocketChannel is set up to wait for incoming connection requests. Requests are satisfied by opening a new receiver and transmitter for each connection.

In the following example, a simple TCP server is created that accepts connections at port 0x5454. The connections understand the OSC commands /pause (disconnect the server for a few seconds), /quit (quit the server), and /dumpOSC (turn on/off printing of message traffic). Each incoming message is replied with a /done message.

    private boolean pause = false; // (must be an instance or static field to be useable
                                   // from an anonymous inner class)

    final Object    sync = new Object();
    final OSCServer c;
    try {
        // create TCP server on loopback port 0x5454
        c = OSCServer.newUsing( OSCServer.TCP, 0x5454, true );
    }
    catch( IOException e1 ) {
        e1.printStackTrace();
        return;
    }

    // now add a listener for incoming messages from
    // any of the active connections
    c.addOSCListener( new OSCListener() {
        public void messageReceived( OSCMessage m, SocketAddress addr, long time )
        {
            // first of all, send a reply message (just a demo)
            try {
                c.send( new OSCMessage( "/done", new Object[] { m.getName() }), addr );
            }
            catch( IOException e1 ) {
                e1.printStackTrace();
            }

            if( m.getName().equals( "/pause" )) {
                // tell the main thread to pause the server,
                // wake up the main thread
                pause = true;
                synchronized( sync ) {
                    sync.notifyAll();
                }
            } else if( m.getName().equals( "/quit" )) {
                // wake up the main thread
                synchronized( sync ) {
                    sync.notifyAll();
                }
            } else if( m.getName().equals( "/dumpOSC" )) {
                // change dumping behaviour
                c.dumpOSC( ((Number) m.getArg( 0 )).intValue(), System.err );
            }
        }
    });
    try {
        do {
            if( pause ) {
                System.out.println( "  waiting four seconds..." );
                try {
                    Thread.sleep( 4000 );
                }
                catch( InterruptedException e1 ) {}
                pause = false;
            }
            System.out.println( "  start()" );
                        // start the server (make it attentive for incoming connection requests)
            c.start();
            try {
                synchronized( sync ) {
                    sync.wait();
                }
            }
            catch( InterruptedException e1 ) {}

            System.out.println( "  stop()" );
            c.stop();
        } while( pause );
    }
    catch( IOException e1 ) {
        e1.printStackTrace();
    }

    // kill the server, free its resources
    c.dispose();
        
Here is an example of sending commands to this server from SuperCollider:
    n = NetAddr( "127.0.0.1", 0x5454 );
    r = OSCresponderNode( n, '/done', { arg time, resp, msg;
        ("reply : " ++ msg.asString).postln;
    }).add;
    n.connect;
    n.sendMsg( '/dumpOSC', 3 );
    n.sendMsg( '/pause' );
    n.isConnected;      // --> false
    n.connect;
    n.sendMsg( '/quit' );
    r.remove;
        

Since:
NetUtil 0.30
Version:
0.37, 12-May-09
Author:
Hanns Holger Rutz
See Also:
OSCClient
Todo:
should provide means to accept or reject connections, should provide means to close particular connections

Field Summary
protected  OSCPacketCodec defaultCodec
           
 
Fields inherited from interface de.sciss.net.OSCChannel
DEFAULTBUFSIZE, kDumpBoth, kDumpHex, kDumpOff, kDumpText, TCP, UDP
 
Constructor Summary
protected OSCServer(OSCPacketCodec c, String protocol)
           
 
Method Summary
abstract  void addOSCListener(OSCListener listener)
          Registers a listener that gets informed about incoming messages (from any of the connected clients).
abstract  void dispose()
          Destroys the server and frees resources associated with it.
abstract  void dumpIncomingOSC(int mode, PrintStream stream)
          Changes the way incoming messages are dumped to the console.
 void dumpOSC(int mode, PrintStream stream)
          Changes the way processed OSC messages are printed to the standard err console.
abstract  void dumpOutgoingOSC(int mode, PrintStream stream)
          Changes the way outgoing messages are dumped to the console.
abstract  int getBufferSize()
          Queries the buffer size used for coding or decoding OSC messages.
 OSCPacketCodec getCodec()
          Queries the codec used in packet coding and decoding.
abstract  OSCPacketCodec getCodec(SocketAddress target)
          Queries the codec used in packet coding and decoding for a given client socket.
abstract  InetSocketAddress getLocalAddress()
          Queries the server socket's address.
protected  InetSocketAddress getLocalAddress(InetAddress addr, int port)
           
 String getProtocol()
          Queries the transport protocol used by this communicator.
abstract  boolean isActive()
          Checks whether the server is active (was started) or not (is stopped).
static OSCServer newUsing(OSCPacketCodec c, String protocol)
          Creates a new instance of an OSCServer, using a specific codec and transport protocol.
static OSCServer newUsing(OSCPacketCodec c, String protocol, InetSocketAddress localAddress)
          Creates a new instance of an OSCServer, using a given codec, a specific transport protocol and local socket address.
static OSCServer newUsing(OSCPacketCodec c, String protocol, int port)
          Creates a new instance of an OSCServer, using a specific codec and transport protocol and port.
static OSCServer newUsing(OSCPacketCodec c, String protocol, int port, boolean loopBack)
          Creates a new instance of an OSCServer, using a specific codec and transport protocol and port.
static OSCServer newUsing(String protocol)
          Creates a new instance of an OSCServer, using default codec and a specific transport protocol.
static OSCServer newUsing(String protocol, InetSocketAddress localAddress)
          Creates a new instance of an OSCServer, using default codec and a specific transport protocol and local socket address.
static OSCServer newUsing(String protocol, int port)
          Creates a new instance of an OSCServer, using default codec and a specific transport protocol and port.
static OSCServer newUsing(String protocol, int port, boolean loopBack)
          Creates a new instance of an OSCServer, using default codec and a specific transport protocol and port.
abstract  void removeOSCListener(OSCListener listener)
          Unregisters a listener that gets informed about incoming messages
abstract  void send(OSCPacket p, SocketAddress target)
          Sends an OSC packet (bundle or message) to the given network address.
abstract  void setBufferSize(int size)
          Adjusts the buffer size for OSC messages.
 void setCodec(OSCPacketCodec c)
          Specifies which codec is used in packet coding and decoding.
abstract  void setCodec(OSCPacketCodec c, SocketAddress target)
          Specifies which codec is used in packet coding and decoding for a given client socket.
abstract  void start()
          Starts the server.
abstract  void stop()
          Stops the server.
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
 

Field Detail

defaultCodec

protected OSCPacketCodec defaultCodec
Constructor Detail

OSCServer

protected OSCServer(OSCPacketCodec c,
                    String protocol)
Method Detail

newUsing

public static OSCServer newUsing(String protocol)
                          throws IOException
Creates a new instance of an OSCServer, using default codec and a specific transport protocol. It picks an arbitrary free port and uses the local machine's IP. To determine the resulting port, you can use getLocalAddress afterwards.

Parameters:
protocol - the protocol to use, currently either UDP or TCP
Returns:
the newly created server
Throws:
IOException - if a networking error occurs while creating the socket
IllegalArgumentException - if an illegal protocol is used
See Also:
OSCChannel.UDP, OSCChannel.TCP, getLocalAddress()

newUsing

public static OSCServer newUsing(OSCPacketCodec c,
                                 String protocol)
                          throws IOException
Creates a new instance of an OSCServer, using a specific codec and transport protocol. It picks an arbitrary free port and uses the local machine's IP. To determine the resulting port, you can use getLocalAddress afterwards.

Parameters:
c - the codec to use
protocol - the protocol to use, currently either UDP or TCP
Returns:
the newly created server
Throws:
IOException - if a networking error occurs while creating the socket
IllegalArgumentException - if an illegal protocol is used
Since:
NetUtil 0.33
See Also:
OSCChannel.UDP, OSCChannel.TCP, getLocalAddress()

newUsing

public static OSCServer newUsing(String protocol,
                                 int port)
                          throws IOException
Creates a new instance of an OSCServer, using default codec and a specific transport protocol and port. It uses the local machine's IP.

Note that the port specifies the local socket (at which the server listens and from which it sends, or in the case of TCP transport, from which it establishes client connections), it does not determine the remote sockets. The address of a remote client communicating to this server is passed in the messageReceived method of any registered OSCListener, and must be picked up and handed in to the send method to reply back to the client!

Parameters:
protocol - the protocol to use, currently either UDP or TCP
port - the port number for the OSC socket, or 0 to use an arbitrary free port
Returns:
the newly created server
Throws:
IOException - if a networking error occurs while creating the socket
IllegalArgumentException - if an illegal protocol is used

newUsing

public static OSCServer newUsing(OSCPacketCodec c,
                                 String protocol,
                                 int port)
                          throws IOException
Creates a new instance of an OSCServer, using a specific codec and transport protocol and port. It uses the local machine's IP.

Note that the port specifies the local socket (at which the server listens and from which it sends, or in the case of TCP transport, from which it establishes client connections), it does not determine the remote sockets. The address of a remote client communicating to this server is passed in the messageReceived method of any registered OSCListener, and must be picked up and handed in to the send method to reply back to the client!

Parameters:
c - the codec to use
protocol - the protocol to use, currently either UDP or TCP
port - the port number for the OSC socket, or 0 to use an arbitrary free port
Returns:
the newly created server
Throws:
IOException - if a networking error occurs while creating the socket
IllegalArgumentException - if an illegal protocol is used
Since:
NetUtil 0.33

newUsing

public static OSCServer newUsing(String protocol,
                                 int port,
                                 boolean loopBack)
                          throws IOException
Creates a new instance of an OSCServer, using default codec and a specific transport protocol and port. It uses the local machine's IP or the "loopback" address.

Note that the port specifies the local socket (at which the server listens and from which it sends, or in the case of TCP transport, from which it establishes client connections), it does not determine the remote sockets. The address of a remote client communicating to this server is passed in the messageReceived method of any registered OSCListener, and must be picked up and handed in to the send method to reply back to the client!

Parameters:
protocol - the protocol to use, currently either UDP or TCP
port - the port number for the OSC socket, or 0 to use an arbitrary free port
loopBack - if true, the "loopback" address ("127.0.0.1") is used which limits communication to the local machine. If false, the special IP "0.0.0.0" is used which means messages from any IP as well as from the loopback are accepted
Returns:
the newly created server
Throws:
IOException - if a networking error occurs while creating the socket
IllegalArgumentException - if an illegal protocol is used

newUsing

public static OSCServer newUsing(OSCPacketCodec c,
                                 String protocol,
                                 int port,
                                 boolean loopBack)
                          throws IOException
Creates a new instance of an OSCServer, using a specific codec and transport protocol and port. It uses the local machine's IP or the "loopback" address.

Note that the port specifies the local socket (at which the server listens and from which it sends, or in the case of TCP transport, from which it establishes client connections), it does not determine the remote sockets. The address of a remote client communicating to this server is passed in the messageReceived method of any registered OSCListener, and must be picked up and handed in to the send method to reply back to the client!

Parameters:
c - the codec to use
protocol - the protocol to use, currently either UDP or TCP
port - the port number for the OSC socket, or 0 to use an arbitrary free port
loopBack - if true, the "loopback" address ("127.0.0.1") is used which limits communication to the local machine. If false, the special IP "0.0.0.0" is used which means messages from any IP as well as from the loopback are accepted
Returns:
the newly created server
Throws:
IOException - if a networking error occurs while creating the socket
IllegalArgumentException - if an illegal protocol is used
Since:
NetUtil 0.33

newUsing

public static OSCServer newUsing(String protocol,
                                 InetSocketAddress localAddress)
                          throws IOException
Creates a new instance of an OSCServer, using default codec and a specific transport protocol and local socket address.

Parameters:
protocol - the protocol to use, currently either UDP or TCP
localAddress - a valid address to use for the OSC socket. If the port is 0, an arbitrary free port is picked when the receiver is started. (you can find out the actual port in this case by calling getLocalAddress() after the server was started).
Returns:
the newly created server
Throws:
IOException - if a networking error occurs while creating the socket
IllegalArgumentException - if an illegal protocol is used
Since:
NetUtil 0.39
See Also:
OSCChannel.UDP, OSCChannel.TCP, getLocalAddress()

newUsing

public static OSCServer newUsing(OSCPacketCodec c,
                                 String protocol,
                                 InetSocketAddress localAddress)
                          throws IOException
Creates a new instance of an OSCServer, using a given codec, a specific transport protocol and local socket address.

Parameters:
c - the codec to use
protocol - the protocol to use, currently either UDP or TCP
localAddress - a valid address to use for the OSC socket. If the port is 0, an arbitrary free port is picked when the receiver is started. (you can find out the actual port in this case by calling getLocalAddress() after the server was started).
Returns:
the newly created server
Throws:
IOException - if a networking error occurs while creating the socket
IllegalArgumentException - if an illegal protocol is used
Since:
NetUtil 0.39
See Also:
OSCChannel.UDP, OSCChannel.TCP, getLocalAddress()

getProtocol

public String getProtocol()
Description copied from interface: OSCChannel
Queries the transport protocol used by this communicator.

Specified by:
getProtocol in interface OSCChannel
Returns:
the protocol, such as UDP or TCP
See Also:
OSCChannel.UDP, OSCChannel.TCP

getLocalAddress

public abstract InetSocketAddress getLocalAddress()
                                           throws IOException
Queries the server socket's address. This is the address at which the server accepts connections (when using TCP) or receives and sends messages (when using UDP). You can determine the host and port from the returned address by calling getHostName() (or for the IP getAddress().getHostAddress()) and getPort().

Note that if the server is bound to the accept-any IP "0.0.0.0", which happens for example when calling newUsing( <protocol>, 0, false ), the returned IP will be the localhost's IP, so you can patch the result directly into any setTarget call.

Specified by:
getLocalAddress in interface OSCChannel
Returns:
the address of the server's local socket.
Throws:
IOException - if the local host could not be resolved
See Also:
InetSocketAddress.getHostName(), InetSocketAddress.getAddress(), InetSocketAddress.getPort(), getProtocol()

send

public abstract void send(OSCPacket p,
                          SocketAddress target)
                   throws IOException
Sends an OSC packet (bundle or message) to the given network address. The address should correspond to one of the connected clients. Particularly, in TCP mode, trying to send to a client which is not connected will throw an exception. In a future version of NetUtil, there will be an interface to detect clients connecting and disconnecting. For now, clients can be implicitly detected by a registered OSCListener.

Parameters:
p - the packet to send
target - the target address to send the packet to
Throws:
IOException - if a write error, OSC encoding error, buffer overflow error or network error occurs, if no client connection for the given address exists

addOSCListener

public abstract void addOSCListener(OSCListener listener)
Registers a listener that gets informed about incoming messages (from any of the connected clients). You can call this both when the server is active or inactive.

Parameters:
listener - the listener to register

removeOSCListener

public abstract void removeOSCListener(OSCListener listener)
Unregisters a listener that gets informed about incoming messages

Parameters:
listener - the listener to remove from the list of notified objects.

start

public abstract void start()
                    throws IOException
Starts the server. The server becomes attentive to requests for connections from clients, starts to receive OSC messages and is able to reply back to connected clients.

Specified by:
start in interface OSCBidi
Throws:
IOException - if a networking error occurs

isActive

public abstract boolean isActive()
Checks whether the server is active (was started) or not (is stopped).

Specified by:
isActive in interface OSCBidi
Returns:
true if the server is active, false otherwise

stop

public abstract void stop()
                   throws IOException
Stops the server. For TCP mode, this implies that all client connections are closed. Stops listening for incoming OSC traffic.

Specified by:
stop in interface OSCBidi
Throws:
IOException - if a networking error occurs

setBufferSize

public abstract void setBufferSize(int size)
Description copied from interface: OSCChannel
Adjusts the buffer size for OSC messages. This is the maximum size an OSC packet (bundle or message) can grow to.

Specified by:
setBufferSize in interface OSCChannel
Parameters:
size - the new size in bytes.
See Also:
OSCChannel.getBufferSize()

getBufferSize

public abstract int getBufferSize()
Description copied from interface: OSCChannel
Queries the buffer size used for coding or decoding OSC messages. This is the maximum size an OSC packet (bundle or message) can grow to.

Specified by:
getBufferSize in interface OSCChannel
Returns:
the buffer size in bytes.
See Also:
OSCChannel.setBufferSize( int )

setCodec

public void setCodec(OSCPacketCodec c)
Description copied from interface: OSCChannel
Specifies which codec is used in packet coding and decoding.

Specified by:
setCodec in interface OSCChannel
Parameters:
c - the codec to use

getCodec

public OSCPacketCodec getCodec()
Description copied from interface: OSCChannel
Queries the codec used in packet coding and decoding.

Specified by:
getCodec in interface OSCChannel
Returns:
the current codec of this channel
See Also:
OSCPacketCodec.getDefaultCodec()

setCodec

public abstract void setCodec(OSCPacketCodec c,
                              SocketAddress target)
                       throws IOException
Specifies which codec is used in packet coding and decoding for a given client socket.

Parameters:
c - the codec to use
target - the client's address for whom the codec is changed
Throws:
IOException - if a networking error occurs or the client does not exist
Since:
NetUtil 0.33

getCodec

public abstract OSCPacketCodec getCodec(SocketAddress target)
                                 throws IOException
Queries the codec used in packet coding and decoding for a given client socket.

Parameters:
target - the client's address for whom the codec is queried
Returns:
the current codec of this channel
Throws:
IOException - if a networking error occurs or the client does not exist
Since:
NetUtil 0.33
See Also:
OSCPacketCodec.getDefaultCodec()

dumpOSC

public final void dumpOSC(int mode,
                          PrintStream stream)
Description copied from interface: OSCChannel
Changes the way processed OSC messages are printed to the standard err console. By default messages are not printed.

Specified by:
dumpOSC in interface OSCChannel
Parameters:
mode - one of kDumpOff (don't dump, default), kDumpText (dump human readable string), kDumpHex (hexdump), or kDumpBoth (both text and hex)
stream - the stream to print on, or null which is shorthand for System.err
See Also:
OSCChannel.kDumpOff, OSCChannel.kDumpText, OSCChannel.kDumpHex, OSCChannel.kDumpBoth

dumpIncomingOSC

public abstract void dumpIncomingOSC(int mode,
                                     PrintStream stream)
Description copied from interface: OSCBidi
Changes the way incoming messages are dumped to the console. By default incoming messages are not dumped. Incoming messages are those received by the client from the server, before they get delivered to registered OSCListeners.

Specified by:
dumpIncomingOSC in interface OSCBidi
Parameters:
mode - see dumpOSC( int ) for details
stream - the stream to print on, or null which is shorthand for System.err
See Also:
OSCChannel.dumpOSC( int, PrintStream ), OSCBidi.dumpOutgoingOSC( int, PrintStream )

dumpOutgoingOSC

public abstract void dumpOutgoingOSC(int mode,
                                     PrintStream stream)
Description copied from interface: OSCBidi
Changes the way outgoing messages are dumped to the console. By default outgoing messages are not dumped. Outgoing messages are those send via send.

Specified by:
dumpOutgoingOSC in interface OSCBidi
Parameters:
mode - see dumpOSC( int ) for details
stream - the stream to print on, or null which is shorthand for System.err
See Also:
OSCChannel.dumpOSC( int, PrintStream ), OSCBidi.dumpIncomingOSC( int, PrintStream )

dispose

public abstract void dispose()
Destroys the server and frees resources associated with it. This automatically stops the server and closes the networking channels. Do not use this server instance any more after calling dispose.

Specified by:
dispose in interface OSCChannel

getLocalAddress

protected InetSocketAddress getLocalAddress(InetAddress addr,
                                            int port)
                                     throws UnknownHostException
Throws:
UnknownHostException