Browse Source

a bunch of stuff i forget. sorry for the bad msg

John 1 year ago
parent
commit
c6643b356c
5 changed files with 206 additions and 110 deletions
  1. 97 76
      numberConverter.lua
  2. 64 26
      osc.lua
  3. 7 1
      rerouterator.lua
  4. 29 5
      routing.lua
  5. 9 2
      serverFunction.lua

+ 97 - 76
numberConverter.lua

@@ -1,99 +1,120 @@
 local numberConverter = {}
 local bit = require("bit")
 
-function numberConverter.toNetworkInt(originalNumber)
-  local byteA = bit.band(originalNumber,0xff)
-
-  local byteB = bit.band(originalNumber,0xff00)
-  byteB = bit.rshift(byteB,8)
-
-  local byteC = bit.band(originalNumber,0xff0000)
-  byteC = bit.rshift(byteC,16)
-
-  local byteD = bit.band(originalNumber,0xff000000)
-  byteD = bit.rshift(byteD,24)
-
-  return (string.char(byteA) ..
-          string.char(byteB) ..
-          string.char(byteC) ..
-          string.char(byteD))
-end
 
 -- nic'd these from stack overflow
 -- https://stackoverflow.com/a/19996852
 function numberConverter.float2hex(n)
-    if n == 0.0 then return 0.0 end
-
-    local sign = 0
-    if n < 0.0 then
-        sign = 0x80
-        n = -n
-    end
-
-    local mant, expo = math.frexp(n)
-    local hext = {}
-
-    if mant ~= mant then
-        hext[#hext+1] = string.char(0xFF, 0x88, 0x00, 0x00)
-
-    elseif mant == math.huge or expo > 0x80 then
-        if sign == 0 then
-            hext[#hext+1] = string.char(0x7F, 0x80, 0x00, 0x00)
-        else
-            hext[#hext+1] = string.char(0xFF, 0x80, 0x00, 0x00)
-        end
-
-    elseif (mant == 0.0 and expo == 0) or expo < -0x7E then
-        hext[#hext+1] = string.char(sign, 0x00, 0x00, 0x00)
-
+  if n == 0.0 then return 0.0 end
+  local sign = 0
+  if n < 0.0 then
+    sign = 0x80
+    n = -n
+  end
+  local mant, expo = math.frexp(n)
+  local hext = {}
+  if mant ~= mant then
+    hext[#hext+1] = string.char(0xFF, 0x88, 0x00, 0x00)
+  elseif mant == math.huge or expo > 0x80 then
+    if sign == 0 then
+      hext[#hext+1] = string.char(0x7F, 0x80, 0x00, 0x00)
     else
-        expo = expo + 0x7E
-        mant = (mant * 2.0 - 1.0) * math.ldexp(0.5, 24)
-        hext[#hext+1] = string.char(sign + math.floor(expo / 0x2),
-                                    (expo % 0x2) * 0x80 + math.floor(mant / 0x10000),
-                                    math.floor(mant / 0x100) % 0x100,
-                                    mant % 0x100)
+      hext[#hext+1] = string.char(0xFF, 0x80, 0x00, 0x00)
     end
-
-    return tonumber(string.gsub(table.concat(hext),"(.)",
-                                function (c) return string.format("%02X%s",string.byte(c),"") end), 16)
+  elseif (mant == 0.0 and expo == 0) or expo < -0x7E then
+    hext[#hext+1] = string.char(sign, 0x00, 0x00, 0x00)
+  else
+    expo = expo + 0x7E
+    mant = (mant * 2.0 - 1.0) * math.ldexp(0.5, 24)
+    hext[#hext+1] = string.char(sign + math.floor(expo / 0x2),
+                                (expo % 0x2) * 0x80 + math.floor(mant / 0x10000),
+                                math.floor(mant / 0x100) % 0x100,
+                                mant % 0x100)
+  end
+
+  return tonumber(string.gsub(table.concat(hext),"(.)",
+  function (c) return string.format("%02X%s",string.byte(c),"") end), 16)
 end
 
 -- nic'd these from stack overflow
 -- https://stackoverflow.com/a/19996852
 function numberConverter.hex2float(c)
-    if c == 0 then return 0.0 end
-    local c = string.gsub(string.format("%X", c),"(..)",function (x) return string.char(tonumber(x, 16)) end)
-    local b1,b2,b3,b4 = string.byte(c, 1, 4)
-    local sign = b1 > 0x7F
-    local expo = (b1 % 0x80) * 0x2 + math.floor(b2 / 0x80)
-    local mant = ((b2 % 0x80) * 0x100 + b3) * 0x100 + b4
-
-    if sign then
-        sign = -1
+  if c == 0 then return 0.0 end
+  local c = string.gsub(string.format("%X", c),"(..)",function (x) return string.char(tonumber(x, 16)) end)
+  local b1,b2,b3,b4 = string.byte(c, 1, 4)
+  local sign = b1 > 0x7F
+  local expo = (b1 % 0x80) * 0x2 + math.floor(b2 / 0x80)
+  local mant = ((b2 % 0x80) * 0x100 + b3) * 0x100 + b4
+  if sign then
+    sign = -1
+  else
+    sign = 1
+  end
+  local n
+  if mant == 0 and expo == 0 then
+    n = sign * 0.0
+  elseif expo == 0xFF then
+    if mant == 0 then
+      n = sign * math.huge
     else
-        sign = 1
+      n = 0.0/0.0
     end
-
-    local n
-
-    if mant == 0 and expo == 0 then
-        n = sign * 0.0
-    elseif expo == 0xFF then
-        if mant == 0 then
-            n = sign * math.huge
-        else
-            n = 0.0/0.0
-        end
-    else
-        n = sign * math.ldexp(1.0 + mant / 0x800000, expo - 0x7F)
-    end
-
-    return n
+  else
+    n = sign * math.ldexp(1.0 + mant / 0x800000, expo - 0x7F)
+  end
+  return n
 end
 
 function numberConverter.toNetworkFloat(f)
   local n = numberConverter.float2hex(f)
   return numberConverter.toNetworkInt(n)
 end
+
+function numberConverter.toNetworkInt(originalNumber)
+  local byteA = bit.band(originalNumber,0xff)
+  local byteB = bit.band(originalNumber,0xff00)
+  byteB = bit.rshift(byteB,8)
+  local byteC = bit.band(originalNumber,0xff0000)
+  byteC = bit.rshift(byteC,16)
+  local byteD = bit.band(originalNumber,0xff000000)
+  byteD = bit.rshift(byteD,24)
+
+  return (string.char(byteD) ..
+          string.char(byteC) ..
+          string.char(byteB) ..
+          string.char(byteA))
+end
+
+function numberConverter.toNetworkNumber(originalNumber)
+  local n = originalNumber
+  if type(originalNumber) == "string" then
+    n = tonumber(originalNumber)
+  end
+
+  if n == math.floor(n) then
+    return numberConverter.toNetworkInt(n)
+  else
+    return numberConverter.toNetworkFloat(n)
+  end
+end
+
+function numberConverter.intToLuaNumber(netNumString)
+  local retval = 0
+  local byteD = netNumString:sub(1,1):byte()
+  local byteC = netNumString:sub(2,2):byte()
+  local byteB = netNumString:sub(3,3):byte()
+  local byteA = netNumString:sub(4,4):byte()
+
+  retval = retval + byteA
+  retval = retval + bit.lshift(byteB,8)
+  retval = retval + bit.lshift(byteC,16)
+  retval = retval + bit.lshift(byteD,24)
+  return retval
+end
+
+function numberConverter.floatToLuaNumber(netNumString)
+  local hexes = numberConverter.intToLuaNumber(netNumString)
+  return numberConverter.hex2float(hexes)
+end
+
 return numberConverter

+ 64 - 26
osc.lua

@@ -1,20 +1,70 @@
 local osc = {}
+local numberConverter = require("numberConverter")
+local messageMetatable = {
+  __index = function(self, index)
+    if index ~= "pack" and index ~= "unpack" then
+      return osc[index]
+    end
+  end,
+}
 
 function osc.toOSCString(original)
-  local newstr = original .. '\0'
-  while ((#newstr)) % 4 ~= 0 do
-    newstr = newstr .. '\0'
+  local valid = #original % 4 == 0 
+  valid = valid and original:sub(#original) == string.char(0)
+  -- we should not attempt to make an already valid osc string into an osc string
+  if not valid then
+    local newstr = original .. '\0'
+    while ((#newstr)) % 4 ~= 0 do
+      newstr = newstr .. '\0'
+    end
+    return newstr
+  else
+    return original
+  end
+end
+
+function osc.appendArgument(self, newArgument, knownType)
+  if knownType then
+    self.argString = self.argString .. knownType
+    table.insert(self, newArgument)
+  else
+    -- type check and update arg string
+    if type(newArgument) == "number" then
+      if newArgument == math.floor(newArgument) then
+        self.argString = self.argString .. "i"
+        table.insert(self, numberConverter.toNetworkInt(newArgument))
+      else
+        self.argString = self.argString .. "f"
+        table.insert(self, numberConverter.toNetworkFloat(newArgument))
+      end
+    elseif type(newArgument) == "string" then
+
+      self.argString = self.argString .. "s"
+      table.insert(self, osc.toOSCString(newArgument))
+    else
+      error("invalid type for OSC message: " .. type(newArgument))
+    end
   end
-  return newstr
 end
 
-function osc.appendArgument(self, newArgument)
-  table.insert(self, newArgument)
+function osc.getArgument(self, index)
+  local type = self.argString:sub(index+1,index+1)
+  if type == 'i' then
+    return numberConverter.intToLuaNumber(self[index])
+  elseif type == 'f' then
+    return numberConverter.floatToLuaNumber(self[index])
+  elseif type == 's' then
+    return self[index]:match("[^%z]*")
+  else
+    error("this should be impossible")
+  end
 end
 
 function osc.unpack(rawDataGram)
   local msg = {}
-  msg.appendArgument = osc.appendArgument
+  setmetatable(msg,messageMetatable)
+  -- msg.appendArgument = osc.appendArgument
+  -- msg.getArgument = osc.getArgument
 
   -- grab address
   -- this nifty patter to match OSC strings only works if you know there is a non-zero character after
@@ -23,7 +73,6 @@ function osc.unpack(rawDataGram)
 
   -- grab argString
   msg.argString = rawDataGram:match("[^%z]+", addressEnd+1)
-  msg.argString = osc.toOSCString(msg.argString)
 
   --       start of arg       len of str       offset for the nulls
   argEnd = addressStart + 1 + #msg.argString + 2
@@ -59,35 +108,24 @@ end
 
 -- packs our message table back into a string that is ready to get shot over the network
 function osc.pack(tbl)
-  local oscMessage = tbl.addr .. tbl.argString
+  local oscMessage = tbl.addr .. osc.toOSCString(tbl.argString)
   for i=1, #tbl, 1 do
     oscMessage = oscMessage .. tbl[i]
   end
   return oscMessage
 end
 
-function osc.create(addr, argString, ...)
+function osc.create(addr, ...)
   local arg = {...}
   local msg = {
     addr = osc.toOSCString(addr),
-    argString = osc.toOSCString(argString),
-    appendArgument = osc.appendArgument
+    --appendArgument = osc.appendArgument,
+    --getArgument = osc.getArgument,
+    argString = ",",
   }
 
-  local numberofArguments = argString:len() - 1
-  local numberConverter = require("numberConverter")
-
-  for i=1,numberofArguments,1 do
-    local argType = argString:sub(i+1,i+1)
-    if argType == 'i' then
-      local netNum = numberConverter.toNetworkInt(tonumber(arg[i]))
-      msg:appendArgument(netNum)
-    elseif argType == 'f' then
-      local netVal = numberConverter.toNetworkFloat(arg[i])
-      msg:appendArgument(netVal)
-    elseif argType == 's' then
-      msg:appendArgument(osc.toOSCString(select(i,...)))
-    end
+  for _, a in pairs(arg) do
+    osc.appendArgument(msg,a)
   end
 
   return msg

+ 7 - 1
rerouterator.lua

@@ -7,7 +7,7 @@ local socket = require("socket")
 local routing = require[[live]].require("routing")
 local serverFunction = require("serverFunction")
 
-local pretty = require[[pl.pretty]]
+pretty = require[[pl.pretty]]
 
 --set up cliargs
 local function print_version()
@@ -18,12 +18,14 @@ local function print_version()
   print("\t- " .. socket._VERSION)
   os.exit(0)
 end
+
 cli:flag("-v, --version", "prints rerouterator's version, and the versions of it's dependencies", print_version)
 cli:set_name("rerouterator")
 cli:option("-n, --hostname=HOSTNAME","the hostname to listen on.", "0.0.0.0")
 cli:option("-l, --listen-port=port","the port to listen on.", {6312})
 cli:option("-f, --forward-port=port","the ports to send routed messages to.", {6311})
 cli:option("-r, --route \"routing\"","add a routing", {})
+cli:option("-c, --config <config file>","add a file with routings in it. One per line", {})
 
 local args, cliErr = cli:parse(arg)
 
@@ -36,6 +38,10 @@ end
 -- set up routing with the cli stuff
 routing.addFromTable(args.route)
 
+for _, filename in pairs(args.config) do
+  routing.addFromFile(filename)
+end
+
 local serverRoutines = {}
 for i=1,#args["listen-port"],1 do
   serverRoutines[i] = coroutine.create(serverFunction)

+ 29 - 5
routing.lua

@@ -72,11 +72,35 @@ end
 
 function routing.createRoutedMessages(incomingMessage)
   local outgoingMessages = {}
-  local routings = routingTable[incomingMessage.addr]
-  for _, route in pairs(routings) do
-    -- create a new message
-    -- set message addr to routing outgoing
-    -- loop over swizzles and add
+  local searchStr = incomingMessage.addr:match("[^%z]+")
+  local routings = routingTable[searchStr]
+
+  if incomingMessage.addr:match("/rerouterator.*") then
+    print("control messages not yet supported")
+  elseif not routings then
+    -- we have no appropriate rules just forward the message unaltered
+    table.insert(outgoingMessages, incomingMessage)
+  else
+    for _, route in pairs(routings) do
+      local newaddr = osc.toOSCString(route.outgoing)
+      -- create a new message
+      local newMsg = osc.create(newaddr)
+      -- loop over swizzles and add the appropriate arguments
+      for _, s in pairs(route.swizzle) do
+        if type(s) == "number" and math.floor(s) == s then
+          osc.appendArgument(newMsg, incomingMessage[s], incomingMessage.argString:sub(s+1,s+1))
+        elseif s:match("#%d+") then
+          local nStr = tonumber(s:match("%d+"))
+          osc.appendArgument(newMsg,nStr)
+        elseif s:match('[^%z]+') then
+          local stringLit = s:match('[^%z]+')
+          osc.appendArgument(newMsg, stringLit)
+        else
+          error("invalid swizzle" .. "(" .. s .. ")")
+        end
+      end
+      table.insert(outgoingMessages, newMsg)
+    end
   end
   return outgoingMessages
 end

+ 9 - 2
serverFunction.lua

@@ -1,7 +1,8 @@
-local osc = require("osc")
+local osc = require[[live]].require("osc")
 local socket = require("socket")
 local routing = require[[live]].require("routing")
 
+
 local function servingFunction (host, port)
   -- server setup
   print("Binding to host '" .. host .. "' and port " .. port .. "...")
@@ -17,9 +18,15 @@ local function servingFunction (host, port)
   while true do
     local dgram = udp:receivefrom()
     if dgram then
+      print("# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #")
+      print("# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #")
+      print("# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #")
+      print("# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #")
       local incoming = osc.unpack(dgram)
       local outgoings = routing.createRoutedMessages(incoming)
-      require[[pl.pretty]].dump(outgoings)
+      for _, out in pairs(outgoings) do
+        udp:sendto(osc.pack(out),"127.0.0.1",6969)
+      end
     end
     coroutine.yield()
   end