summaryrefslogblamecommitdiffstats
path: root/src/main/java/org/openslx/taskmanager/tasks/WakeOnLan.java
blob: 246749aebe35e54535fdee9c838df41fba9a3357 (plain) (tree)
1
2
3
4
5
6
7
8
9
10

                                      







                                     
 




                                                
                                           
 






                                                                                                                                                     

                              
 

                          
 

                                


                         


                                    

                              










                                                         















                                                                                        

                                                       










                                                                                                           
                 





                                                                      





                                   

                                           
                             




                                                                            
                         
 



                                                       
 



























                                                                                                                
                                                                                                                                                














                                                                                                                                            












                                                         
package org.openslx.taskmanager.tasks;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
import java.net.UnknownHostException;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.openslx.satserver.util.Util;
import org.openslx.taskmanager.api.AbstractTask;

import com.google.gson.annotations.Expose;

public class WakeOnLan extends AbstractTask
{

	private static final Pattern RE_IPv4 =
			Pattern.compile( "^(\\d+)\\.(\\d+)\\.(\\d+)\\.(\\d+)$" );
	private static final Pattern RE_MAC =
			Pattern.compile( "^([0-9a-f]{2})[:-]([0-9a-f]{2}+)[:-]([0-9a-f]{2}+)[:-]([0-9a-f]{2}+)[:-]([0-9a-f]{2}+)[:-]([0-9a-f]{2}+)$",
					Pattern.CASE_INSENSITIVE );

	@Expose
	private String[] macs;

	@Expose
	private String ip;

	@Expose
	private String password;
	
	@Expose
	private int port;

	private StatusObject status;

	private byte[] buffer;

	@Override
	protected boolean initTask()
	{
		status = new StatusObject();
		this.setStatusObject( status );
		if ( macs == null || macs.length == 0 ) {
			status.addMsg( "Macs empty" );
		}
		if ( Util.isEmpty( ip ) ) {
			status.addMsg( "IP empty" );
		}
		int pwlen = 0;
		Matcher m = null;
		if ( !Util.isEmpty( password ) ) {
			m = RE_IPv4.matcher( password );
			if ( m.matches() ) {
				pwlen = 4;
			} else {
				m = RE_MAC.matcher( password );
				if ( m.matches() ) {
					pwlen = 6;
				}
			}
			if ( pwlen == 0 ) {
				status.addMsg( "Invalid password format: " + password );
			}
		}
		if ( !Util.isEmpty( status.messages ) )
			return false;
		buffer = new byte[ 17 * 6 + pwlen ];
		if ( pwlen != 0 ) {
			try {
				for ( int i = 0; i < pwlen; ++i ) {
					int x = Integer.parseInt( m.group( i + 1 ), pwlen == 4 ? 10 : 16 );
					buffer[17 * 6 + i] = (byte)x;
				}
			} catch ( Throwable t ) {
				status.addMsg( "Invalid octet in password" );
				return false;
			}
		}
		if ( this.port == 0 ) {
			this.port = 9;
		} else if ( this.port > 65535 || this.port < 0 ) {
			status.addMsg( "Invalid port: " + this.port );
			return false;
		}
		return true;
	}

	@Override
	protected boolean execute()
	{
		DatagramSocket sock = null;
		try {
			try {
				sock = new DatagramSocket();
				sock.setBroadcast( true );
			} catch ( SocketException e ) {
				status.addMsg( "Cannot create UDP socket" );
				return false;
			}

			// Sync bytes
			for ( int i = 0; i < 6; ++i ) {
				buffer[i] = -1;
			}

			// Repeat three times
			for ( int reps = 0; reps < 3; ++reps ) {
				if ( reps != 0 ) {
					try {
						Thread.sleep( 600 );
					} catch ( InterruptedException t ) {
						Thread.currentThread().interrupt();
						break;
					}
				}
				// For each MAC
				for ( int mi = 0; mi < macs.length; ++mi ) {
					Matcher m = RE_MAC.matcher( macs[mi] );
					if ( !m.matches() ) {
						status.addMsg( "Cannot parse MAC address " + macs[mi] );
						continue;
					}
					try {
						for ( int i = 0; i < 6; ++i ) {
							byte x = (byte)Integer.parseInt( m.group( i + 1 ), 16 );
							for ( int offset = 0; offset < 16; ++offset ) {
								buffer[6 + offset * 6 + i] = x;
							}
						}
					} catch ( NumberFormatException e ) {
						status.addMsg( "Invalid octet in MAC address: " + macs[mi] );
						continue;
					}
					DatagramPacket dp = new DatagramPacket( buffer, buffer.length, InetAddress.getByName( ip ), this.port );
					try {
						sock.send( dp );
						status.addMsg( "Sent packet to " + macs[mi] );
					} catch ( IOException e ) {
						status.addMsg( "Error sending UDP packet to " + ip + "/" + macs[mi] + ": " + e.toString() );
					}
				}
			}
		} catch ( UnknownHostException e ) {
			status.addMsg( "Cannot resolve " + ip );
			return false;
		} finally {
			Util.multiClose( sock );
		}
		return true;
	}

	class StatusObject
	{
		private String messages = "";

		public void addMsg( String str )
		{
			messages = messages + "\n" + str;
		}
	}

}