David 9 年 前
コミット
b7ca51a5da
2 ファイル変更100 行追加0 行削除
  1. 20 0
      client.py
  2. 80 0
      server.py

+ 20 - 0
client.py

@@ -0,0 +1,20 @@
+#!/usr/bin/env python3
+import socket
+import sys
+
+if len(sys.argv) != 2:
+    print("Usage: 1 argument: MAC")
+    sys.exit(1)
+
+UDP_PORT = 9
+MAC = sys.argv[1].replace(":", "")
+MAC = MAC[::-1]  # Reverse the MAC address to create a 'sleep' packet
+
+msg = 6 * "FF"
+msg = msg + 16 * MAC
+msg = bytes.fromhex(msg)
+
+sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
+sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
+sock.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
+sock.sendto(msg, ('255.255.255.255', UDP_PORT))

+ 80 - 0
server.py

@@ -0,0 +1,80 @@
+#!/usr/bin/env python3
+
+import socket
+import platform
+from subprocess import check_output, Popen
+
+INVALID = "INVALID"
+WAKE = "WAKE"
+SLEEP = "SLEEP"
+OTHERS = "OTHERS"
+
+
+def parse_magic_packet(packet):
+    frame = packet[0:6].hex()
+    macs = set()
+    for _ in range(0, 16):
+        packet = packet[6:]
+        mac = packet[:6].hex()
+        macs.add(mac)
+
+    if frame != "ff"*6 or len(macs) != 1:
+        return INVALID
+
+    mac = list(macs)[0].lower()
+    if mac in MACS:
+        return WAKE
+
+    if mac[::-1] in MACS:
+        return SLEEP
+
+    return OTHERS
+
+
+def get_windows_macs():
+    import re
+    out = check_output(["ipconfig", "/all"]).decode("ascii").split("\n")
+    match_mac = r"\s(?P<mac>[0-9a-f-]{17})\s"
+    ret = []
+    for line in out:
+        matches = re.search(match_mac, line, flags=re.IGNORECASE)
+        if matches:
+            ret.append(matches.group("mac").replace("-", "").lower())
+    return ret
+
+
+def get_linux_macs():
+    import netifaces
+    ret = []
+    ifaces = netifaces.interfaces()
+    ifaces.remove('lo')
+    for i in ifaces:
+        addresses = netifaces.ifaddresses(i)[netifaces.AF_LINK]
+        ret.append(addresses[0]['addr'].replace(":", "")).lower()
+    return ret
+
+
+def get_macs():
+    if platform.system() == 'Windows':
+        return get_windows_macs()
+    else:
+        return get_linux_macs()
+
+
+def suspend():
+    if platform.system() == 'Windows':
+        Popen(["rundll32.exe", "powrprof.dll,SetSuspendState", "0,1,0"])
+    else:
+        Popen(["systemctl", "suspend"])
+
+
+sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
+sock.bind(('', 9))
+MACS = get_macs()
+
+while True:
+    msg, addr = sock.recvfrom(1024)
+    res = parse_magic_packet(msg)
+    print(res)
+    if res == "SLEEP":
+        suspend()