kaitoy / pcap4j

A Java library for capturing, crafting, and sending packets.

Home Page:https://www.pcap4j.org/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Interrupt pool Thread

MarkusRost opened this issue · comments

Hello,

I use the SendArpRequest example to read the MAC adress of an other IP. When the IP is not reachable, a thread named "pool-15-thread-1" is not stop and still alive.

How can I stop these Thread?

Here my code:
`import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import org.pcap4j.core.BpfProgram.BpfCompileMode;
import org.pcap4j.core.NotOpenException;
import org.pcap4j.core.PacketListener;
import org.pcap4j.core.PcapHandle;
import org.pcap4j.core.PcapNativeException;
import org.pcap4j.core.PcapNetworkInterface;
import org.pcap4j.core.PcapNetworkInterface.PromiscuousMode;
import org.pcap4j.core.Pcaps;
import org.pcap4j.packet.ArpPacket;
import org.pcap4j.packet.EthernetPacket;
import org.pcap4j.packet.Packet;
import org.pcap4j.packet.namednumber.ArpHardwareType;
import org.pcap4j.packet.namednumber.ArpOperation;
import org.pcap4j.packet.namednumber.EtherType;
import org.pcap4j.util.ByteArrays;
import org.pcap4j.util.MacAddress;

public class SendArpRequest
{
private static final String COUNT_KEY = SendArpRequest.class.getName() + ".count";
private static int COUNT;
private static final String READ_TIMEOUT_KEY = SendArpRequest.class.getName() + ".readTimeout";
private static int READ_TIMEOUT; // [ms]
private static final String SNAPLEN_KEY = SendArpRequest.class.getName() + ".snaplen";
private static int SNAPLEN; // [bytes]

private String sourceIP = "";

private MacAddress sourceMac = MacAddress.getByName( "fe:00:01:02:03:04" );
private static MacAddress resolvedAddr = null;
private String destinationIP = "";

private Debug debug;
private ConfigRead config;

public SendArpRequest( Debug d, ConfigRead c, String sourceIP, String sourceMac ) 
{
	this.debug = d;
	this.config = c;
	this.sourceIP = sourceIP;
	this.sourceMac = MacAddress.getByName( sourceMac );
	
	COUNT = Integer.getInteger( COUNT_KEY, config.getArpCount() );
	READ_TIMEOUT = Integer.getInteger( READ_TIMEOUT_KEY, config.getArpTimeout() ); // [ms]
	SNAPLEN = Integer.getInteger( SNAPLEN_KEY, config.getArpPacketSize() ); // [bytes]
	
	debug.print( 2, "ARP Objekt initialisiert mit SourceIP: " + sourceIP + " und Source Mac: " + sourceMac );
}

public String searchMacAddress( String destinationIP ) throws RuntimeException
{
	debug.print( 2, "Suche nach Macadresse für: " + destinationIP );
    
	String erg = "";
	Boolean state = true;
	
	this.destinationIP = destinationIP;
	resolvedAddr = null;
	
	/*
	System.out.println(COUNT_KEY + ": " + COUNT);
    System.out.println(READ_TIMEOUT_KEY + ": " + READ_TIMEOUT);
    System.out.println(SNAPLEN_KEY + ": " + SNAPLEN);
    System.out.println("\n");
	*/
	
    PcapNetworkInterface nif;

    try
    {
    	nif = Pcaps.getDevByAddress( InetAddress.getByName( this.sourceIP ) );
    }
    catch( Exception e )
    {
    	debug.print( 1, "Source Netzwerk Interface nicht gefunden: " + e.getMessage() );
    	return erg;
    }

    if( nif == null )
    {
    	debug.print( 1, "Source Netzwerk Interface nicht gefunden!" );
    	return erg;
    }

    debug.print( 2, "Suche über folgendes Inerface: " + nif.getName() + " (" + nif.getDescription() + ")" );
    
    PcapHandle handle = null;
    PcapHandle sendHandle = null;
    ExecutorService pool = null;

    try
    {
	    handle = nif.openLive( SNAPLEN, PromiscuousMode.PROMISCUOUS, READ_TIMEOUT );
	    sendHandle = nif.openLive( SNAPLEN, PromiscuousMode.PROMISCUOUS, READ_TIMEOUT );
	    pool = Executors.newSingleThreadExecutor();
	    	    	
    	handle.setFilter( "arp and src host " + destinationIP + " and dst host " + this.sourceIP + " and ether dst " + Pcaps.toBpfString( this.sourceMac ), BpfCompileMode.OPTIMIZE );

    	PacketListener listener = new PacketListener()
    	{
            public void gotPacket( Packet packet )
            {
            	if( packet.contains( ArpPacket.class ))
            	{
            		ArpPacket arp = packet.get( ArpPacket.class );
            		if( arp.getHeader().getOperation().equals( ArpOperation.REPLY ))
            		{
            			SendArpRequest.resolvedAddr = arp.getHeader().getSrcHardwareAddr();
            		}
            	}

            	debug.print( 3, "Empfangenes Packet: " + packet );

            }
    	};

    	Task t = new Task( handle, listener );
	    pool.execute( t );
	
	    ArpPacket.Builder arpBuilder = new ArpPacket.Builder();
	    try
	    {
	    	arpBuilder
	          .hardwareType( ArpHardwareType.ETHERNET )
	          .protocolType( EtherType.IPV4 )
	          .hardwareAddrLength( (byte)MacAddress.SIZE_IN_BYTES )
	          .protocolAddrLength( (byte)ByteArrays.INET4_ADDRESS_SIZE_IN_BYTES )
	          .operation( ArpOperation.REQUEST )
	          .srcHardwareAddr( this.sourceMac )
	          .srcProtocolAddr( InetAddress.getByName( this.sourceIP ))
	          .dstHardwareAddr( MacAddress.ETHER_BROADCAST_ADDRESS )
	          .dstProtocolAddr( InetAddress.getByName( destinationIP ));
	    }
	    catch( UnknownHostException e )
	    {
	    	debug.print( 1, "Fehler beim Bau des ARP Pakets: " + e.getMessage() );
	    	return erg;
	    }

	    EthernetPacket.Builder etherBuilder = new EthernetPacket.Builder();
	    etherBuilder.dstAddr( MacAddress.ETHER_BROADCAST_ADDRESS )
	    	.srcAddr( this.sourceMac )
	        .type( EtherType.ARP )
	        .payloadBuilder( arpBuilder )
	        .paddingAtBuild( true );

	    for( int i = 0; i < COUNT; i++ ) 
	    {
	        Packet p = etherBuilder.build();
	        
	        debug.print( 3, "Gesendetes Packet: " + p );
	        
	        sendHandle.sendPacket(p);
	        
	        try
	        {
	        	Thread.sleep( 1000 );
	        }
	        catch( InterruptedException e )
	        {
	        	break;
	        }
	    }
	    
	    debug.print( 2, "Pakete gesendet" );
	    
	    int i = 0;
	    
	    while( true )
	    {
	    	if( resolvedAddr != null )
	    	{
	    		break;
	    	}
	    	
	    	i = i + 1;
	    	
	    	if( i >= 10 )
	    	{
	    		pool.shutdown();
	    		pool.shutdownNow();
	    		throwRuntimeException();
	    	}
	    	
	    	try
	        {
	        	Thread.sleep( 100 );
	        }
	        catch( InterruptedException e )
	        {
	        	break;
	        }
	    }
    }
    catch( RuntimeException re )
    {
    	debug.print( 1, "Runtime Error bei ARP Abfrage: " + re.getMessage() );
    	state = false;
    	throw new RuntimeException( re );
    }
    catch( Exception e )
    {
    	debug.print( 1, "Fehler bei ARP Abfrage: " + e.getMessage() );
    	return erg;
	}
    finally
    {
    	if( state == true )
    	{	
	    	if (handle != null && handle.isOpen())
	    	{
	    		handle.close();
	    	}
	    	if (sendHandle != null && sendHandle.isOpen())
	    	{
	    		sendHandle.close();
	    	}
	    	if (pool != null && !pool.isShutdown())
	    	{
	    		pool.shutdown();
	    	}
    	}
    	
    	debug.print( 2, destinationIP + " was resolved to " + resolvedAddr );
    }
    return resolvedAddr.toString();
}

private void throwRuntimeException()
{
	throw new RuntimeException( "RunTime Fehler bei " + destinationIP );
}

private static class Task implements Runnable
{

	private PcapHandle handle;
	private PacketListener listener;

    public Task(PcapHandle handle, PacketListener listener) 
    {
    	this.handle = handle;
    	this.listener = listener;
    }

    @Override
    public void run() 
    {
    	try
    	{
    		handle.loop(COUNT, listener);
    	} 
    	catch (PcapNativeException e)
    	{
    		e.printStackTrace();
    	}
    	catch (InterruptedException e)
    	{
    		e.printStackTrace();
    	} 
    	catch (NotOpenException e)
    	{
    		e.printStackTrace();
    	}
    }

}

}`

Thanks

Markus