MCGroupImplpublic class MCGroupImpl extends Object implements com.aelitis.net.udp.mc.MCGroup
Fields Summary |
---|
private static final int | TTL | private static final int | PACKET_SIZE | private static Map | singletons | private static org.gudy.azureus2.core3.util.AEMonitor | class_mon | private com.aelitis.net.udp.mc.MCGroupAdapter | adapter | private String | group_address_str | private int | group_port | private int | control_port | protected InetSocketAddress | group_address | private String[] | selected_interfaces | private boolean | ttl_problem_reported | private boolean | sso_problem_reported | protected org.gudy.azureus2.core3.util.AEMonitor | this_mon | private Map | current_registrations |
Constructors Summary |
---|
public MCGroupImpl(com.aelitis.net.udp.mc.MCGroupAdapter _adapter, String _group_address, int _group_port, int _control_port, String[] _interfaces)
adapter = _adapter;
group_address_str = _group_address;
group_port = _group_port;
control_port = _control_port;
selected_interfaces = _interfaces;
try{
group_address = new InetSocketAddress(InetAddress.getByName(group_address_str), 0 );
processNetworkInterfaces( true );
UTTimer timer = new UTTimerImpl( "MCGroup:refresher", true );
timer.addPeriodicEvent(
60*1000,
new UTTimerEventPerformer()
{
public void
perform(
UTTimerEvent event )
{
try{
processNetworkInterfaces( false );
}catch( Throwable e ){
adapter.log(e);
}
}
});
}catch( Throwable e ){
throw( new MCGroupException( "Failed to initialise MCGroup", e ));
}
|
Methods Summary |
---|
public int | getControlPort()
return( control_port );
| public static com.aelitis.net.udp.mc.impl.MCGroupImpl | getSingleton(com.aelitis.net.udp.mc.MCGroupAdapter adapter, java.lang.String group_address, int group_port, int control_port, java.lang.String[] interfaces)
try{
class_mon.enter();
String key = group_address + ":" + group_port + ":" + control_port;
MCGroupImpl singleton = (MCGroupImpl)singletons.get( key );
if ( singleton == null ){
singleton = new MCGroupImpl( adapter, group_address, group_port, control_port, interfaces );
singletons.put( key, singleton );
}
return( singleton );
}finally{
class_mon.exit();
}
| protected void | handleSocket(java.net.NetworkInterface network_interface, java.net.InetAddress local_address, java.net.DatagramSocket socket, boolean log_on_stop)
long successful_accepts = 0;
long failed_accepts = 0;
int port = socket.getLocalPort();
try{
// introduce a timeout so that when a Network interface changes we don't sit here
// blocking forever and thus never realise that we should shutdown
socket.setSoTimeout( 30000 );
}catch( Throwable e ){
}
while(true){
if ( !validNetworkAddress( network_interface, local_address )){
if ( log_on_stop ){
adapter.trace(
"group = " + group_address +"/" +
network_interface.getName()+":"+
network_interface.getDisplayName() + " - " + local_address + ": stopped" );
}
return;
}
try{
byte[] buf = new byte[PACKET_SIZE];
DatagramPacket packet = new DatagramPacket(buf, buf.length );
socket.receive( packet );
successful_accepts++;
failed_accepts = 0;
receivePacket( network_interface, local_address, packet );
}catch( SocketTimeoutException e ){
}catch( Throwable e ){
failed_accepts++;
adapter.trace( "MCGroup: receive failed on port " + port + ":" + e.getMessage());
if (( failed_accepts > 100 && successful_accepts == 0 ) || failed_accepts > 1000 ){
adapter.trace( " too many failures, abandoning" );
break;
}
}
}
| protected boolean | interfaceSelected(java.net.NetworkInterface ni)
if ( selected_interfaces != null && selected_interfaces.length > 0 ){
boolean ok = false;
for (int i=0;i<selected_interfaces.length;i++){
if ( ni.getName().equalsIgnoreCase( selected_interfaces[i] )){
ok = true;
break;
}
}
return( ok );
}else{
return( true );
}
| protected void | processNetworkInterfaces(boolean start_of_day)
Map new_registrations = new HashMap();
List changed_interfaces = new ArrayList();
try{
this_mon.enter();
Enumeration network_interfaces = NetworkInterface.getNetworkInterfaces();
while (network_interfaces.hasMoreElements()){
final NetworkInterface network_interface = (NetworkInterface)network_interfaces.nextElement();
if ( !interfaceSelected( network_interface )){
if ( start_of_day ){
adapter.trace( "ignoring interface " + network_interface.getName() + ":" + network_interface.getDisplayName() + ", not selected" );
}
continue;
}
Set old_address_set = (Set)current_registrations.get( network_interface );
if ( old_address_set == null ){
old_address_set = new HashSet();
}
Set new_address_set = new HashSet();
new_registrations.put( network_interface, new_address_set );
Enumeration ni_addresses = network_interface.getInetAddresses();
while (ni_addresses.hasMoreElements()){
final InetAddress ni_address = (InetAddress)ni_addresses.nextElement();
new_address_set.add( ni_address );
if ( old_address_set.contains( ni_address )){
// already established
continue;
}
// turn on loopback to see if it helps for local host UPnP devices
// nah, turn it off again, it didn;t
if ( ni_address.isLoopbackAddress()){
if ( start_of_day ){
adapter.trace( "ignoring loopback address " + ni_address + ", interface " + network_interface.getName());
}
continue;
}
if ( ni_address instanceof Inet6Address ){
if ( start_of_day ){
adapter.trace( "ignoring IPv6 address " + ni_address + ", interface " + network_interface.getName());
}
continue;
}
if ( !start_of_day ){
if ( !changed_interfaces.contains( network_interface )){
changed_interfaces.add( network_interface );
}
}
try{
// set up group
final MulticastSocket mc_sock = new MulticastSocket( group_port );
mc_sock.setReuseAddress(true);
// windows 98 doesn't support setTimeToLive
try{
mc_sock.setTimeToLive(TTL);
}catch( Throwable e ){
if ( !ttl_problem_reported ){
ttl_problem_reported = true;
adapter.log( e );
}
}
String addresses_string = "";
Enumeration it = network_interface.getInetAddresses();
while (it.hasMoreElements()){
InetAddress addr = (InetAddress)it.nextElement();
addresses_string += (addresses_string.length()==0?"":",") + addr;
}
adapter.trace( "group = " + group_address +"/" +
network_interface.getName()+":"+
network_interface.getDisplayName() + "-" + addresses_string +": started" );
mc_sock.joinGroup( group_address, network_interface );
mc_sock.setNetworkInterface( network_interface );
// note that false ENABLES loopback mode which is what we want
mc_sock.setLoopbackMode(false);
Runtime.getRuntime().addShutdownHook(
new AEThread("MCGroup:VMShutdown")
{
public void
runSupport()
{
try{
mc_sock.leaveGroup( group_address, network_interface );
}catch( Throwable e ){
adapter.log( e );
}
}
});
new AEThread("MCGroup:MCListener", true )
{
public void
runSupport()
{
handleSocket( network_interface, ni_address, mc_sock, true );
}
}.start();
}catch( Throwable e ){
adapter.log( e );
}
// now do the incoming control listener
try{
final DatagramSocket control_socket = new DatagramSocket( null );
control_socket.setReuseAddress( true );
control_socket.bind( new InetSocketAddress(ni_address, control_port ));
if ( control_port == 0 ){
control_port = control_socket.getLocalPort();
// System.out.println( "local port = " + control_port );
}
new AEThread( "MCGroup:CtrlListener", true )
{
public void
runSupport()
{
handleSocket( network_interface, ni_address, control_socket, false );
}
}.start();
}catch( Throwable e ){
adapter.log( e );
}
}
}
}finally{
current_registrations = new_registrations;
this_mon.exit();
}
for (int i=0;i<changed_interfaces.size();i++){
adapter.interfaceChanged((NetworkInterface)changed_interfaces.get(i));
}
| protected void | receivePacket(java.net.NetworkInterface network_interface, java.net.InetAddress local_address, java.net.DatagramPacket packet)
byte[] data = packet.getData();
int len = packet.getLength();
// System.out.println( "receive: add = " + local_address + ", data = " + new String( data, 0, len ));
adapter.received(
network_interface,
local_address,
(InetSocketAddress)packet.getSocketAddress(),
data,
len );
| public void | sendToGroup(byte[] data)
try{
Enumeration x = NetworkInterface.getNetworkInterfaces();
while( x != null && x.hasMoreElements()){
NetworkInterface network_interface = (NetworkInterface)x.nextElement();
if ( !interfaceSelected( network_interface )){
continue;
}
Enumeration ni_addresses = network_interface.getInetAddresses();
boolean ok = false;
while( ni_addresses.hasMoreElements()){
InetAddress ni_address = (InetAddress)ni_addresses.nextElement();
if ( !( ni_address instanceof Inet6Address || ni_address.isLoopbackAddress())){
ok = true;
break;
}
}
if ( !ok ){
continue;
}
try{
MulticastSocket mc_sock = new MulticastSocket(null);
mc_sock.setReuseAddress(true);
try{
mc_sock.setTimeToLive( TTL );
}catch( Throwable e ){
if ( !ttl_problem_reported ){
ttl_problem_reported = true;
adapter.log( e );
}
}
mc_sock.bind( new InetSocketAddress( control_port ));
mc_sock.setNetworkInterface( network_interface );
// System.out.println( "sendToGroup: ni = " + network_interface.getName() + ", data = " + new String(data));
DatagramPacket packet = new DatagramPacket(data, data.length, group_address.getAddress(), group_port );
mc_sock.send(packet);
mc_sock.close();
}catch( Throwable e ){
if ( !sso_problem_reported ){
sso_problem_reported = true;
adapter.log( e );
}
}
}
}catch( Throwable e ){
throw( new MCGroupException( "sendToGroup failed", e ));
}
| public void | sendToGroup(java.lang.String param_data)
try{
Enumeration x = NetworkInterface.getNetworkInterfaces();
while( x != null && x.hasMoreElements()){
NetworkInterface network_interface = (NetworkInterface)x.nextElement();
if ( !interfaceSelected( network_interface )){
continue;
}
Enumeration ni_addresses = network_interface.getInetAddresses();
InetAddress an_address = null;
while( ni_addresses.hasMoreElements()){
InetAddress ni_address = (InetAddress)ni_addresses.nextElement();
if ( !( ni_address instanceof Inet6Address || ni_address.isLoopbackAddress())){
an_address = ni_address;
break;
}
}
if ( an_address == null){
continue;
}
try{
MulticastSocket mc_sock = new MulticastSocket(null);
mc_sock.setReuseAddress(true);
try{
mc_sock.setTimeToLive( TTL );
}catch( Throwable e ){
if ( !ttl_problem_reported ){
ttl_problem_reported = true;
adapter.log( e );
}
}
mc_sock.bind( new InetSocketAddress( control_port ));
mc_sock.setNetworkInterface( network_interface );
byte[] data = param_data.replaceAll("%AZINTERFACE%", an_address.getHostAddress()).getBytes();
// System.out.println( "sendToGroup: ni = " + network_interface.getName() + ", data = " + new String(data));
DatagramPacket packet = new DatagramPacket(data, data.length, group_address.getAddress(), group_port );
mc_sock.send(packet);
mc_sock.close();
}catch( Throwable e ){
if ( !sso_problem_reported ){
sso_problem_reported = true;
adapter.log( e );
}
}
}
}catch( Throwable e ){
throw( new MCGroupException( "sendToGroup failed", e ));
}
| public void | sendToMember(java.net.InetSocketAddress address, byte[] data)
DatagramSocket reply_socket = null;
// System.out.println( "sendToMember: add = " + address + ", data = " +new String( data ));
try{
reply_socket = new DatagramSocket( null );
reply_socket.setReuseAddress(true);
reply_socket.bind( new InetSocketAddress( group_port ));
DatagramPacket reply_packet = new DatagramPacket(data,data.length,address);
reply_socket.send( reply_packet );
}catch( Throwable e ){
throw( new MCGroupException( "sendToMember failed", e ));
}finally{
if ( reply_socket != null ){
try{
reply_socket.close();
}catch( Throwable e ){
}
}
}
| protected boolean | validNetworkAddress(java.net.NetworkInterface network_interface, java.net.InetAddress ni_address)
try{
this_mon.enter();
Set set = (Set)current_registrations.get( network_interface );
if ( set == null ){
return( false );
}
return( set.contains( ni_address ));
}finally{
this_mon.exit();
}
|
|