From 4b94b61faf1b447dce62b990114b8ed34469bf58 Mon Sep 17 00:00:00 2001 From: Ben Blank Date: Wed, 28 Jan 2015 17:46:22 -0800 Subject: [PATCH 1/4] make the Sides API less suprising when used with the `#` operator and `ipairs` function --- .../opencomputers/loot/OpenOS/lib/sides.lua | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/src/main/resources/assets/opencomputers/loot/OpenOS/lib/sides.lua b/src/main/resources/assets/opencomputers/loot/OpenOS/lib/sides.lua index 7048a92c9..a17d3f66b 100644 --- a/src/main/resources/assets/opencomputers/loot/OpenOS/lib/sides.lua +++ b/src/main/resources/assets/opencomputers/loot/OpenOS/lib/sides.lua @@ -32,6 +32,31 @@ local sides = { forward = 3 } +local metatable = getmetatable(sides) or {} + +-- sides[0..5] are mapped to itertable[1..6]. +local itertable = { + sides[0], + sides[1], + sides[2], + sides[3], + sides[4], + sides[5] +} + +-- Future-proofing against the possible introduction of additional +-- logical sides (e.g. [7] = "all", [8] = "none", etc.). +function metatable.__len(sides) + return #itertable +end + +-- Allow `sides` to be iterated over like a normal (1-based) array. +function metatable.__ipairs(sides) + return ipairs(itertable) +end + +setmetatable(sides, metatable) + ------------------------------------------------------------------------------- return sides From c30d5b29ff98e2f8efdb281acc3da331a492204f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20N=C3=BCcke?= Date: Sun, 1 Feb 2015 14:27:50 +0100 Subject: [PATCH 2/4] Gnah, missed one. Should *fully* fix #859 now. --- src/main/scala/li/cil/oc/server/network/Connector.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/scala/li/cil/oc/server/network/Connector.scala b/src/main/scala/li/cil/oc/server/network/Connector.scala index 977cdc35f..54ef7b6b5 100644 --- a/src/main/scala/li/cil/oc/server/network/Connector.scala +++ b/src/main/scala/li/cil/oc/server/network/Connector.scala @@ -93,7 +93,7 @@ trait Connector extends network.Connector with Node { // we get ignored if our size is zero. localBufferSize = clampedSize if (network != null) { - if (localBufferSize <= 0 && clampedSize > 0) d.addConnector(this) + if (oldSize <= 0 && clampedSize > 0) d.addConnector(this) else if (oldSize > 0 && clampedSize == 0) d.removeConnector(this) else d.globalBufferSize = math.max(d.globalBufferSize - oldSize + clampedSize, 0) } From e6668d59b418c8f2d56d1762cd71baeb6dca1808 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20N=C3=BCcke?= Date: Sun, 1 Feb 2015 14:47:57 +0100 Subject: [PATCH 3/4] Limiting number of parts allowed in network packets as a safeguard for weaker computers, as discussed in #876. Configurable, of course. --- src/main/resources/application.conf | 8 ++++++ src/main/scala/li/cil/oc/Settings.scala | 1 + .../li/cil/oc/server/network/Network.scala | 25 +++++++++++-------- 3 files changed, 24 insertions(+), 10 deletions(-) diff --git a/src/main/resources/application.conf b/src/main/resources/application.conf index ddc69a789..8ef00ee37 100644 --- a/src/main/resources/application.conf +++ b/src/main/resources/application.conf @@ -925,6 +925,14 @@ opencomputers { # not apply to HTTP traffic. maxNetworkPacketSize: 8192 + # The maximum number of "data parts" a network packet is allowed to have. + # When sending a network message, from Lua this may look like so: + # component.modem.broadcast(port, "first", true, "third", 123) + # This limits how many arguments can be passed and are wrapped into a + # packet. This limit mostly serves as a protection for lower-tier + # computers, to avoid them getting nuked by more powerful computers. + maxNetworkPacketParts: 8 + # The maximum number of ports a single network card can have opened at # any given time. maxOpenPorts: 16 diff --git a/src/main/scala/li/cil/oc/Settings.scala b/src/main/scala/li/cil/oc/Settings.scala index 8d3a806ec..619d30c59 100644 --- a/src/main/scala/li/cil/oc/Settings.scala +++ b/src/main/scala/li/cil/oc/Settings.scala @@ -271,6 +271,7 @@ class Settings(val config: Config) { val inputUsername = config.getBoolean("misc.inputUsername") val maxClipboard = config.getInt("misc.maxClipboard") max 0 val maxNetworkPacketSize = config.getInt("misc.maxNetworkPacketSize") max 0 + val maxNetworkPacketParts = config.getInt("misc.maxNetworkPacketParts") max 0 val maxOpenPorts = config.getInt("misc.maxOpenPorts") max 0 val maxWirelessRange = config.getDouble("misc.maxWirelessRange") max 0 val rTreeMaxEntries = 10 diff --git a/src/main/scala/li/cil/oc/server/network/Network.scala b/src/main/scala/li/cil/oc/server/network/Network.scala index 3625d4fda..dc559092e 100644 --- a/src/main/scala/li/cil/oc/server/network/Network.scala +++ b/src/main/scala/li/cil/oc/server/network/Network.scala @@ -662,17 +662,22 @@ object Network extends api.detail.NetworkAPI { // ----------------------------------------------------------------------- // class Packet(var source: String, var destination: String, var port: Int, var data: Array[AnyRef], var ttl: Int = 5) extends api.network.Packet { - val size = Option(data).fold(0)(_.foldLeft(0)((acc, arg) => { - acc + (arg match { - case null | Unit | None => 4 - case _: java.lang.Boolean => 4 - case _: java.lang.Integer => 4 - case _: java.lang.Double => 8 - case value: java.lang.String => value.length max 1 - case value: Array[Byte] => value.length max 1 - case _ => throw new IllegalArgumentException("unsupported data type") + val size = Option(data).fold(0)(values => { + if (values.length > Settings.get.maxNetworkPacketParts) { + throw new IllegalArgumentException("packet has too many parts") + } + values.length * 2 + values.foldLeft(0)((acc, arg) => { + acc + (arg match { + case null | Unit | None => 4 + case _: java.lang.Boolean => 4 + case _: java.lang.Integer => 4 + case _: java.lang.Double => 8 + case value: java.lang.String => value.length max 1 + case value: Array[Byte] => value.length max 1 + case _ => throw new IllegalArgumentException("unsupported data type") + }) }) - })) + }) override def hop() = new Packet(source, destination, port, data, ttl - 1) From 8092fae0a1cc281231c8a3ba16ed0e9af6c23b68 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20N=C3=BCcke?= Date: Sun, 1 Feb 2015 15:07:18 +0100 Subject: [PATCH 4/4] Revert using addresses in VFS back to using proxy objects, since I probably won't ever come around to actually implement mounts and symlinks being saved across reboots anyway. Closes #879. This [partially] reverts commit 42040e2da654d23a74386c5f188aa0053646c100. Conflicts: src/main/resources/assets/opencomputers/loot/OpenOS/lib/filesystem.lua --- .../loot/OpenOS/lib/filesystem.lua | 37 +++++++++---------- 1 file changed, 18 insertions(+), 19 deletions(-) diff --git a/src/main/resources/assets/opencomputers/loot/OpenOS/lib/filesystem.lua b/src/main/resources/assets/opencomputers/loot/OpenOS/lib/filesystem.lua index 9904ed9d8..7edda653b 100644 --- a/src/main/resources/assets/opencomputers/loot/OpenOS/lib/filesystem.lua +++ b/src/main/resources/assets/opencomputers/loot/OpenOS/lib/filesystem.lua @@ -140,7 +140,7 @@ end function filesystem.get(path) local node, rest = findNode(path) if node.fs then - local proxy = component.proxy(node.fs) + local proxy = node.fs path = "" while node and node.parent do path = filesystem.concat(node.name, path) @@ -192,7 +192,7 @@ function filesystem.mount(fs, path) if vnode.fs then return nil, "another filesystem is already mounted here" end - vnode.fs = fs.address + vnode.fs = fs return true end @@ -218,7 +218,7 @@ function filesystem.mounts() table.insert(queue, child) end if node.fs then - return component.proxy(node.fs) or node.fs, path(node) + return node.fs, path(node) end end end @@ -288,7 +288,7 @@ function filesystem.exists(path) return true end if node and node.fs then - return component.proxy(node.fs).exists(rest) + return node.fs.exists(rest) end return false end @@ -299,7 +299,7 @@ function filesystem.size(path) return 0 -- virtual directory or symlink end if node.fs and rest then - return component.proxy(node.fs).size(rest) + return node.fs.size(rest) end return 0 -- no such file or directory end @@ -310,7 +310,7 @@ function filesystem.isDirectory(path) return true -- virtual directory end if node.fs then - return not rest or component.proxy(node.fs).isDirectory(rest) + return not rest or node.fs.isDirectory(rest) end return false end @@ -321,7 +321,7 @@ function filesystem.lastModified(path) return 0 -- virtual directory end if node.fs and rest then - return component.proxy(node.fs).lastModified(rest) + return node.fs.lastModified(rest) end return 0 -- no such file or directory end @@ -333,7 +333,7 @@ function filesystem.list(path) end local result, reason if node and node.fs then - result, reason = component.proxy(node.fs).list(rest or "") + result, reason = node.fs.list(rest or "") end result = result or {} if not vrest then @@ -367,7 +367,7 @@ function filesystem.makeDirectory(path) end local node, rest = findNode(path) if node.fs and rest then - return component.proxy(node.fs).makeDirectory(rest) + return node.fs.makeDirectory(rest) end if node.fs then return nil, "virtual directory with that name already exists" @@ -393,7 +393,7 @@ function filesystem.remove(path) local function removePhysical() node, rest = findNode(path) if node.fs and rest then - return component.proxy(node.fs).remove(rest) + return node.fs.remove(rest) end return false end @@ -417,8 +417,8 @@ function filesystem.rename(oldPath, newPath) local oldNode, oldRest = findNode(oldPath) local newNode, newRest = findNode(newPath) if oldNode.fs and oldRest and newNode.fs and newRest then - if oldNode.fs == newNode.fs then - return component.proxy(oldNode.fs).rename(oldRest, newRest) + if oldNode.fs.address == newNode.fs.address then + return oldNode.fs.rename(oldRest, newRest) else local result, reason = filesystem.copy(oldPath, newPath) if result then @@ -465,7 +465,7 @@ end function fileStream:close() if self.handle then - component.proxy(self.fs).close(self.handle) + self.fs.close(self.handle) self.handle = nil end end @@ -474,21 +474,21 @@ function fileStream:read(n) if not self.handle then return nil, "file is closed" end - return component.proxy(self.fs).read(self.handle, n) + return self.fs.read(self.handle, n) end function fileStream:seek(whence, offset) if not self.handle then return nil, "file is closed" end - return component.proxy(self.fs).seek(self.handle, whence, offset) + return self.fs.seek(self.handle, whence, offset) end function fileStream:write(str) if not self.handle then return nil, "file is closed" end - return component.proxy(self.fs).write(self.handle, str) + return self.fs.write(self.handle, str) end function filesystem.open(path, mode) @@ -503,7 +503,7 @@ function filesystem.open(path, mode) return nil, "file not found" end - local handle, reason = component.proxy(node.fs).open(rest, mode) + local handle, reason = node.fs.open(rest, mode) if not handle then return nil, reason end @@ -512,8 +512,7 @@ function filesystem.open(path, mode) local function cleanup(self) if not self.handle then return end - local proxy = component.proxy(self.fs) - if proxy then pcall(proxy.close, self.handle) end + pcall(self.fs.close, self.handle) end local metatable = {__index = fileStream, __gc = cleanup,