173 lines
		
	
	
		
			4.6 KiB
		
	
	
	
		
			Go
		
	
	
	
			
		
		
	
	
			173 lines
		
	
	
		
			4.6 KiB
		
	
	
	
		
			Go
		
	
	
	
| package handler
 | |
| 
 | |
| import (
 | |
| 	"fmt"
 | |
| 	"net"
 | |
| 	"net/http"
 | |
| 	"time"
 | |
| 
 | |
| 	"github.com/labstack/echo/v4"
 | |
| 	"github.com/labstack/gommon/log"
 | |
| 	"github.com/ngoduykhanh/wireguard-ui/model"
 | |
| 	"github.com/ngoduykhanh/wireguard-ui/store"
 | |
| 	"github.com/sabhiram/go-wol/wol"
 | |
| )
 | |
| 
 | |
| type WakeOnLanHostSavePayload struct {
 | |
| 	Name          string `json:"name"`
 | |
| 	MacAddress    string `json:"mac_address"`
 | |
| 	OldMacAddress string `json:"old_mac_address"`
 | |
| }
 | |
| 
 | |
| func createError(c echo.Context, err error, msg string) error {
 | |
| 	log.Error(msg, err)
 | |
| 	return c.JSON(
 | |
| 		http.StatusInternalServerError,
 | |
| 		jsonHTTPResponse{
 | |
| 			false,
 | |
| 			msg})
 | |
| }
 | |
| 
 | |
| func GetWakeOnLanHosts(db store.IStore) echo.HandlerFunc {
 | |
| 	return func(c echo.Context) error {
 | |
| 		var err error
 | |
| 
 | |
| 		hosts, err := db.GetWakeOnLanHosts()
 | |
| 		if err != nil {
 | |
| 			return createError(c, err, fmt.Sprintf("wake_on_lan_hosts database error: %s", err))
 | |
| 		}
 | |
| 
 | |
| 		err = c.Render(http.StatusOK, "wake_on_lan_hosts.html", map[string]interface{}{
 | |
| 			"baseData": model.BaseData{Active: "wake_on_lan_hosts", CurrentUser: currentUser(c), Admin: isAdmin(c)},
 | |
| 			"hosts":    hosts,
 | |
| 			"error":    "",
 | |
| 		})
 | |
| 		if err != nil {
 | |
| 			return createError(c, err, fmt.Sprintf("wake_on_lan_hosts.html render error: %s", err))
 | |
| 		}
 | |
| 
 | |
| 		return nil
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func SaveWakeOnLanHost(db store.IStore) echo.HandlerFunc {
 | |
| 	return func(c echo.Context) error {
 | |
| 		var payload WakeOnLanHostSavePayload
 | |
| 		err := c.Bind(&payload)
 | |
| 		if err != nil {
 | |
| 			log.Error("Wake On Host Save Payload Bind Error: ", err)
 | |
| 			return c.JSON(http.StatusInternalServerError, payload)
 | |
| 		}
 | |
| 
 | |
| 		var host = model.WakeOnLanHost{
 | |
| 			MacAddress: payload.MacAddress,
 | |
| 			Name:       payload.Name,
 | |
| 		}
 | |
| 		if len(payload.OldMacAddress) != 0 { // Edit
 | |
| 			if payload.OldMacAddress != payload.MacAddress { // modified mac address
 | |
| 				oldHost, err := db.GetWakeOnLanHost(payload.OldMacAddress)
 | |
| 				if err != nil {
 | |
| 					return createError(c, err, fmt.Sprintf("Wake On Host Update Err: %s", err))
 | |
| 				}
 | |
| 
 | |
| 				if payload.OldMacAddress != payload.MacAddress {
 | |
| 					existHost, _ := db.GetWakeOnLanHost(payload.MacAddress)
 | |
| 					if existHost != nil {
 | |
| 						return createError(c, nil, "Mac Address already exists.")
 | |
| 					}
 | |
| 				}
 | |
| 
 | |
| 				err = db.DeleteWakeOnHostLanHost(payload.OldMacAddress)
 | |
| 				if err != nil {
 | |
| 					return createError(c, err, fmt.Sprintf("Wake On Host Update Err: %s", err))
 | |
| 				}
 | |
| 				host.LatestUsed = oldHost.LatestUsed
 | |
| 			}
 | |
| 			err = db.SaveWakeOnLanHost(host)
 | |
| 		} else { // new
 | |
| 			existHost, _ := db.GetWakeOnLanHost(payload.MacAddress)
 | |
| 			if existHost != nil {
 | |
| 				return createError(c, nil, "Mac Address already exists.")
 | |
| 			}
 | |
| 
 | |
| 			err = db.SaveWakeOnLanHost(host)
 | |
| 		}
 | |
| 
 | |
| 		if err != nil {
 | |
| 			return createError(c, err, fmt.Sprintf("Wake On Host Save Error: %s", err))
 | |
| 		}
 | |
| 
 | |
| 		return c.JSON(http.StatusOK, host)
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func DeleteWakeOnHost(db store.IStore) echo.HandlerFunc {
 | |
| 	return func(c echo.Context) error {
 | |
| 		var macAddress = c.Param("mac_address")
 | |
| 		var host, err = db.GetWakeOnLanHost(macAddress)
 | |
| 
 | |
| 		if err != nil {
 | |
| 			log.Error("Wake On Host Delete Error: ", err)
 | |
| 			return createError(c, err, fmt.Sprintf("Wake On Host Delete Error: %s", macAddress))
 | |
| 		}
 | |
| 
 | |
| 		err = db.DeleteWakeOnHost(*host)
 | |
| 		if err != nil {
 | |
| 			return createError(c, err, fmt.Sprintf("Wake On Host Delete Error: %s", macAddress))
 | |
| 		}
 | |
| 
 | |
| 		return c.JSON(http.StatusOK, nil)
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func WakeOnHost(db store.IStore) echo.HandlerFunc {
 | |
| 	return func(c echo.Context) error {
 | |
| 		macAddress := c.Param("mac_address")
 | |
| 		host, err := db.GetWakeOnLanHost(macAddress)
 | |
| 
 | |
| 		now := time.Now().UTC()
 | |
| 		host.LatestUsed = &now
 | |
| 		err = db.SaveWakeOnLanHost(*host)
 | |
| 		if err != nil {
 | |
| 			return createError(c, err, fmt.Sprintf("Latest Used Update Error: %s", macAddress))
 | |
| 		}
 | |
| 
 | |
| 		magicPacket, err := wol.New(macAddress)
 | |
| 		if err != nil {
 | |
| 			return createError(c, err, fmt.Sprintf("Magic Packet Create Error: %s", macAddress))
 | |
| 		}
 | |
| 
 | |
| 		bytes, err := magicPacket.Marshal()
 | |
| 		if err != nil {
 | |
| 			return createError(c, err, fmt.Sprintf("Magic Packet Bytestream Error: %s", macAddress))
 | |
| 		}
 | |
| 
 | |
| 		udpAddr, err := net.ResolveUDPAddr("udp", "255.255.255.255:0")
 | |
| 		if err != nil {
 | |
| 			return createError(c, err, fmt.Sprintf("ResolveUDPAddr Error: %s", macAddress))
 | |
| 		}
 | |
| 
 | |
| 		// Grab a UDP connection to send our packet of bytes.
 | |
| 		conn, err := net.DialUDP("udp", nil, udpAddr)
 | |
| 		if err != nil {
 | |
| 			return err
 | |
| 		}
 | |
| 		defer func(conn *net.UDPConn) {
 | |
| 			err := conn.Close()
 | |
| 			if err != nil {
 | |
| 				log.Error(err)
 | |
| 			}
 | |
| 		}(conn)
 | |
| 
 | |
| 		n, err := conn.Write(bytes)
 | |
| 		if err == nil && n != 102 {
 | |
| 			return createError(c, nil, fmt.Sprintf("magic packet sent was %d bytes (expected 102 bytes sent)", n))
 | |
| 		}
 | |
| 		if err != nil {
 | |
| 			return createError(c, err, fmt.Sprintf("Network Send Error: %s", macAddress))
 | |
| 		}
 | |
| 
 | |
| 		return c.JSON(http.StatusOK, host.LatestUsed)
 | |
| 	}
 | |
| }
 |