From 4e33221e9809bfb1d206ca5f080fb9294bad523f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20N=C3=BCcke?= Date: Thu, 15 Jan 2015 20:03:04 +0100 Subject: [PATCH] Added `modem.get/setWakeMessage` for wake-on-lan. Closes #781, #700. --- .../cil/oc/server/component/NetworkCard.scala | 35 +++++++++++++++++-- .../server/component/RedstoneSignaller.scala | 10 +++--- 2 files changed, 38 insertions(+), 7 deletions(-) diff --git a/src/main/scala/li/cil/oc/server/component/NetworkCard.scala b/src/main/scala/li/cil/oc/server/component/NetworkCard.scala index 0992adc10..111e76ff2 100644 --- a/src/main/scala/li/cil/oc/server/component/NetworkCard.scala +++ b/src/main/scala/li/cil/oc/server/component/NetworkCard.scala @@ -1,5 +1,6 @@ package li.cil.oc.server.component +import com.google.common.base.Charsets import li.cil.oc.Settings import li.cil.oc.api import li.cil.oc.api.Network @@ -21,6 +22,8 @@ class NetworkCard(val host: EnvironmentHost) extends prefab.ManagedEnvironment { protected val openPorts = mutable.Set.empty[Int] + protected var wakeMessage: Option[String] = None + // ----------------------------------------------------------------------- // @Callback(doc = """function(port:number):boolean -- Opens the specified port. Returns true if the port was opened.""") @@ -75,6 +78,19 @@ class NetworkCard(val host: EnvironmentHost) extends prefab.ManagedEnvironment { @Callback(direct = true, doc = """function():number -- Gets the maximum packet size (config setting).""") def maxPacketSize(context: Context, args: Arguments): Array[AnyRef] = result(Settings.get.maxNetworkPacketSize) + @Callback(direct = true, doc = """function():string -- Get the current wake-up message.""") + def getWakeMessage(context: Context, args: Arguments): Array[AnyRef] = result(wakeMessage.orNull) + + @Callback(doc = """function(message:string):string -- Set the wake-up message.""") + def setWakeMessage(context: Context, args: Arguments): Array[AnyRef] = { + val oldMessage = wakeMessage + if (args.optAny(0, null) == null) + wakeMessage = None + else + wakeMessage = Option(args.checkString(0)) + result(oldMessage.orNull) + } + protected def doSend(packet: Packet) { node.sendToReachable("network.message", packet) } @@ -109,8 +125,19 @@ class NetworkCard(val host: EnvironmentHost) extends prefab.ManagedEnvironment { } protected def receivePacket(packet: Packet, distance: Double) { - if (packet.source != node.address && Option(packet.destination).forall(_ == node.address) && openPorts.contains(packet.port)) { - node.sendToReachable("computer.signal", Seq("modem_message", packet.source, Int.box(packet.port), Double.box(distance)) ++ packet.data: _*) + if (packet.source != node.address && Option(packet.destination).forall(_ == node.address)) { + if (openPorts.contains(packet.port)) { + node.sendToReachable("computer.signal", Seq("modem_message", packet.source, Int.box(packet.port), Double.box(distance)) ++ packet.data: _*) + } + // Accept wake-up messages regardless of port because we close all ports + // when our computer shuts down. + packet.data match { + case Array(message: Array[Byte]) if wakeMessage.contains(new String(message, Charsets.UTF_8)) => + node.sendToNeighbors("computer.start") + case Array(message: String) if wakeMessage.contains(message) => + node.sendToNeighbors("computer.start") + case _ => + } } } @@ -121,12 +148,16 @@ class NetworkCard(val host: EnvironmentHost) extends prefab.ManagedEnvironment { assert(openPorts.isEmpty) openPorts ++= nbt.getIntArray("openPorts") + if (nbt.hasKey("wakeMessage")) { + wakeMessage = Option(nbt.getString("wakeMessage")) + } } override def save(nbt: NBTTagCompound) { super.save(nbt) nbt.setIntArray("openPorts", openPorts.toArray) + wakeMessage.foreach(nbt.setString("wakeMessage", _)) } // ----------------------------------------------------------------------- // diff --git a/src/main/scala/li/cil/oc/server/component/RedstoneSignaller.scala b/src/main/scala/li/cil/oc/server/component/RedstoneSignaller.scala index 1b911599e..b43e293c0 100644 --- a/src/main/scala/li/cil/oc/server/component/RedstoneSignaller.scala +++ b/src/main/scala/li/cil/oc/server/component/RedstoneSignaller.scala @@ -1,6 +1,5 @@ package li.cil.oc.server.component -import li.cil.oc.Settings import li.cil.oc.api.machine.Arguments import li.cil.oc.api.machine.Callback import li.cil.oc.api.machine.Context @@ -15,10 +14,11 @@ trait RedstoneSignaller extends prefab.ManagedEnvironment { @Callback(direct = true, doc = """function():number -- Get the current wake-up threshold.""") def getWakeThreshold(context: Context, args: Arguments): Array[AnyRef] = result(wakeThreshold) - @Callback(doc = """function(threshold:number) -- Set the wake-up threshold.""") + @Callback(doc = """function(threshold:number):number -- Set the wake-up threshold.""") def setWakeThreshold(context: Context, args: Arguments): Array[AnyRef] = { + val oldThreshold = wakeThreshold wakeThreshold = args.checkInteger(0) - null + result(oldThreshold) } // ----------------------------------------------------------------------- // @@ -34,11 +34,11 @@ trait RedstoneSignaller extends prefab.ManagedEnvironment { override def load(nbt: NBTTagCompound): Unit = { super.load(nbt) - wakeThreshold = nbt.getInteger(Settings.namespace + "wakeThreshold") + wakeThreshold = nbt.getInteger("wakeThreshold") } override def save(nbt: NBTTagCompound): Unit = { super.save(nbt) - nbt.setInteger(Settings.namespace + "wakeThreshold", wakeThreshold) + nbt.setInteger("wakeThreshold", wakeThreshold) } }