socket.http freezing mushclient

Posted by Victorious on Sat 21 Dec 2013 03:45 AM — 6 posts, 23,122 views.

#0
I just started experimenting with socket.http for my plugin and started noticing that while the code was running (e.g retrieving version information from a website), you can't do anything in mushclient before the code finishes. Is it possible to have the code not cause the freezing?
Australia Forum Administrator #1
I think you can do non-blocking calls, but I can't remember how. Browse the documentation for the Lua socket library, it may have examples.
#2
I've been looking into using threads to try solving this problem and based on section 9.4 of the programming in lua manual, I've came up with the following code. I'm still trying to grasp the concepts but so far, this increases download speeds but mushclient is still unresponsive during this process because the dispatcher() has control.


    threads = {}    -- list of all live threads
    function get (host, file, output)
      -- create coroutine
      local co = coroutine.create(function ()
        download(host, file, output)
      end)
      -- insert it in the list
      table.insert(threads, co)
    end

    function dispatcher ()
      while true do
        local n = table.getn(threads)
        if n == 0 then break end   -- no more threads to run
        local connections = {}
        for i=1,n do
          local status, res = coroutine.resume(threads[i])
          if res == nil then -- thread finished its task
            table.remove(threads, i)
            break
          else    -- timeout
            table.insert(connections, res)
          end
        end
        if table.getn(connections) == n then
          socket.select(connections)
        end
      end
    end

    function receive (connection)
connection:settimeout(0.051)   -- do not block
      local s, status = connection:receive(2^10)
      if status == "timeout" then
        coroutine.yield(connection)
      end
      return s, status
    end

    function download (host, file, output)
f = io.output(output)
      local c = assert(socket.connect(host, 80))
      local count = 0    -- counts number of bytes read
      c:send("GET " .. file .. " HTTP/1.0\r\n\r\n")
      while true do
s, status = receive(c)

if s ~= nil then
        count = count + string.len(s)
--assembles the actual file
if actualfile == nil then
actualfile = s
else
actualfile = actualfile..s
end
end

        if status == "closed" then break end
      end
      c:close()
      print(file, count) --filename and length
f:write(actualfile)
f:flush()
f:close()
    end


[EDIT] Code tags added.
Amended on Sun 22 Dec 2013 12:38 PM by Nick Gammon
Australia Forum Administrator #3
I think the problem with trying to make something non-blocking is that you would then have to periodically check if the I/O was completed. I'm not sure how you would do that, maybe with a timer.
#4
Hmmm, maybe something like lua lanes might work but was having trouble compiling the dll and getting it integrated with mushclient.
Australia Forum Administrator #5
I think you will find there are problems with this sort of thing because MUSHclient has a "main loop" and non-blocking code tends to want to have its own "main loop".