• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2011 jMonkeyEngine
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are
7  * met:
8  *
9  * * Redistributions of source code must retain the above copyright
10  *   notice, this list of conditions and the following disclaimer.
11  *
12  * * Redistributions in binary form must reproduce the above copyright
13  *   notice, this list of conditions and the following disclaimer in the
14  *   documentation and/or other materials provided with the distribution.
15  *
16  * * Neither the name of 'jMonkeyEngine' nor the names of its contributors
17  *   may be used to endorse or promote products derived from this software
18  *   without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
24  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
27  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
28  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
29  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
30  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  */
32 
33 package com.jme3.network.kernel.udp;
34 
35 import com.jme3.network.kernel.Connector;
36 import com.jme3.network.kernel.ConnectorException;
37 import java.io.IOException;
38 import java.net.*;
39 import java.nio.ByteBuffer;
40 import java.util.concurrent.atomic.AtomicBoolean;
41 
42 
43 /**
44  *  A straight forward datagram socket-based UDP connector
45  *  implementation.
46  *
47  *  @version   $Revision: 8843 $
48  *  @author    Paul Speed
49  */
50 public class UdpConnector implements Connector
51 {
52     private DatagramSocket sock = new DatagramSocket();
53     private SocketAddress remoteAddress;
54     private byte[] buffer = new byte[65535];
55     private AtomicBoolean connected = new AtomicBoolean(false);
56 
57     /**
58      *  In order to provide proper available() checking, we
59      *  potentially queue one datagram.
60      */
61     private DatagramPacket pending;
62 
63     /**
64      *  Creates a new UDP connection that send datagrams to the
65      *  specified address and port.
66      */
UdpConnector( InetAddress remote, int remotePort )67     public UdpConnector( InetAddress remote, int remotePort ) throws IOException
68     {
69         InetSocketAddress localSocketAddress = new InetSocketAddress(0);
70         this.sock = new DatagramSocket( localSocketAddress );
71         remoteAddress = new InetSocketAddress( remote, remotePort );
72 
73         // Setup to receive only from the remote address
74         sock.connect( remoteAddress );
75 
76         connected.set(true);
77     }
78 
checkClosed()79     protected void checkClosed()
80     {
81         if( sock == null )
82             throw new ConnectorException( "Connection is closed:" + remoteAddress );
83     }
84 
isConnected()85     public boolean isConnected()
86     {
87         if( sock == null )
88             return false;
89         return sock.isConnected();
90     }
91 
close()92     public void close()
93     {
94         checkClosed();
95         DatagramSocket temp = sock;
96         sock = null;
97         connected.set(false);
98         temp.close();
99     }
100 
101     /**
102      *  This always returns false since the simple DatagramSocket usage
103      *  cannot be run in a non-blocking way.
104      */
available()105     public boolean available()
106     {
107         // It would take a separate thread or an NIO Selector based implementation to get this
108         // to work.  If a polling strategy is never employed by callers then it doesn't
109         // seem worth it to implement all of that just for this method.
110         checkClosed();
111         return false;
112     }
113 
read()114     public ByteBuffer read()
115     {
116         checkClosed();
117 
118         try {
119             DatagramPacket packet = new DatagramPacket( buffer, buffer.length );
120             sock.receive(packet);
121 
122             // Wrap it in a ByteBuffer for the caller
123             return ByteBuffer.wrap( buffer, 0, packet.getLength() );
124         } catch( IOException e ) {
125             if( !connected.get() ) {
126                 // Nothing to see here... just move along
127                 return null;
128             }
129             throw new ConnectorException( "Error reading from connection to:" + remoteAddress, e );
130         }
131     }
132 
write( ByteBuffer data )133     public void write( ByteBuffer data )
134     {
135         checkClosed();
136 
137         try {
138             DatagramPacket p = new DatagramPacket( data.array(), data.position(), data.remaining(),
139                                                    remoteAddress );
140             sock.send(p);
141         } catch( IOException e ) {
142             throw new ConnectorException( "Error writing to connection:" + remoteAddress, e );
143         }
144     }
145 }
146 
147