Ejemplo n.º 1
0
func wakeUp(host, mac string) (bool, error) {
	result := make(chan *time.Duration)
	go ping.Ping(host, 5*time.Second, result)
	if <-result != nil {
		log.Printf("Host %s responding to pings, not waking up.\n", host)
		return false, nil
	}

	// Parse MAC address
	parts := strings.Split(mac, ":")
	if len(parts) != 6 {
		log.Fatalf(`MAC address "%s" does not consist of 6 parts`, mac)
	}
	macParts := make([]uint8, 6)
	for idx, str := range parts {
		converted, err := strconv.ParseUint(str, 16, 8)
		if err != nil {
			log.Fatalf("Invalid MAC address part: %s: %v\n", str, err)
		}
		macParts[idx] = uint8(converted)
	}

	// Send magic Wake-On-LAN packet
	payload := make([]byte, 102)
	for idx := 0; idx < 6; idx++ {
		payload[idx] = 0xff
	}
	for n := 0; n < 16; n++ {
		for part := 0; part < 6; part++ {
			payload[6+(n*6)+part] = macParts[part]
		}
	}
	socket, err := net.DialUDP("udp4", nil, &net.UDPAddr{
		IP: net.IPv4(255, 255, 255, 255),
		// udp/9 is the discard protocol
		Port: 9,
	})
	if err != nil {
		log.Fatalf("Cannot open UDP broadcast socket: %v\n", err)
	}
	socket.Write(payload)
	socket.Close()
	log.Printf("Sent magic packet to %02x:%02x:%02x:%02x:%02x:%02x\n",
		macParts[0], macParts[1], macParts[2], macParts[3], macParts[4], macParts[5])

	timeout := 120 * time.Second
	packetSent := time.Now()
	for time.Since(packetSent) < timeout {
		go ping.Ping(host, 1*time.Second, result)
		if <-result != nil {
			log.Printf("Host %s woke up after waiting %v.\n", host, time.Since(packetSent))
			return true, nil
		}
		time.Sleep(500 * time.Millisecond)
	}

	return true, fmt.Errorf("Host %s not responding to pings within %v after sending magic packet", host, timeout)
}
Ejemplo n.º 2
0
func pingRemote() {
	result := make(chan *time.Duration)
	go ping.Ping(*remoteIp, 1*time.Second, result)
	reachable := <-result != nil
	if reachable {
		state = waiting
		return
	}

	log.Printf("target unresponsive, sending magic packet to %s…\n", *remoteMac)
	if err := exec.Command(*wolCommand, *remoteMac).Run(); err != nil {
		log.Fatal(err)
	}
	for second := 0; second < *wakeTimeout; second++ {
		go ping.Ping(*remoteIp, 1*time.Second, result)
		if <-result != nil {
			log.Printf("target reachable after %d seconds\n", second)
			break
		}
	}
	state = waiting
}
Ejemplo n.º 3
0
func pingBeast() {
	for {
		result := make(chan *time.Duration)
		go ping.Ping("beast", 1*time.Second, result)
		latency := <-result

		stateMu.Lock()
		state.beastPowered = latency != nil
		if state.beastPowered {
			lastContact["beast"] = time.Now()
		}
		stateMu.Unlock()
		stateChanged.Broadcast()

		if latency != nil {
			time.Sleep(1*time.Second - *latency)
		}
	}
}
Ejemplo n.º 4
0
// Runs infinitely as a goroutine, periodically pinging samba users.
func pingUsers() {
	for {
		statusLock.Lock()
		hosts = getSessionHostnames()
		statusLock.Unlock()

		// This default will lead to a shutdown in case the machine gets booted
		// and nobody starts using it within 10 minutes, which is intentional.
		// The machine should only be booted when usage is imminent.
		reachable := false
		if len(hosts) > 0 {
			result := make(chan *time.Duration)
			for _, host := range hosts {
				go ping.Ping(host, 5*time.Second, result)
			}
			reachable = <-result != nil
		}
		statusLock.Lock()
		reachableUsers = reachable
		statusLock.Unlock()
		time.Sleep(10 * time.Second)
	}
}