* * * * *

   In theory, it should work the same on the testing server as well as the
                              production server

I haven't mentioned the other server I wrote, GLV-1.12556 [1]. I wrote it a
few months ago mainly as a means to test out the Lua TLS (Transport Layer
Security) wrapper [2] I wrote [3] beacuse otherwise, the wrapper is just an
intellectual exercise. It implements the Gemini protocol [4] which lies
somewhat between gopher and HTTP (HyperText Transport Protocol).

One issue keeps rearing its ugly head—files larger than some size just aren't
transfered. It just causes an error that I haven't been able to figure out.
The first time this happened several months ago, I hacked at the code and
thought I got it working. Alas, it's happening again. I received word today
of it failing to send files beyond a certain size, and yes, I can reproduce
it.

But here's the kicker—I can reproduce it on my live server [5] but I can't
reproduce it locally. It only seems to happen across the Internet. So any
testing now has to happen “live” (as it were) on the “production server”
(grrrrrr). I fixed some possible issues, maybe, like this bit of code:

-----[ Lua ]-----
 ios._drain = function(self,data)
   local bytes = self.__ctx:write(data)

   if bytes == tls.ERROR then

     -- --------------------------------------------------------------------
     -- I was receiving "Resource temporarily unavailable" and trying again,
     -- but that strategy fails upon failure to read a certificate.  So now
     -- I'm back to returning an error.  Let's hope this works this time.
     -- --------------------------------------------------------------------

     return false,self.__ctx:error()

   elseif bytes == tls.WANT_INPUT or bytes == tls.WANT_OUTPUT then
     self.__resume = true
     coroutine.yield()
     return self:_drain(data)

   elseif bytes < #data then
     nfl.SOCKETS:update(conn,"w")
     self.__resume = true
     coroutine.yield()
     return self:_drain(data:sub(bytes+1,-1))
   end

   return true
 end
-----[ END OF LINE ]-----

Upon looking over this code, I rethought the logic if dealing with
tls.WANT_INPUT (the TLS layer needs the underlying socket descriptor to be
readable) or tls.WANT_OUTPUT (the TLS layer needs the underlying socket
descriptor to be writable) with the same bit of code, and rewrote it thusly:

-----[ Lua ]-----
 ios._drain = function(self,data)
   local bytes = self.__ctx:write(data)

   if bytes == tls.ERROR then

     -- --------------------------------------------------------------------
     -- I was receiving "Resource temporarily unavailable" and trying again,
     -- but that strategy fails upon failure to read a certificate.  So now
     -- I'm back to returning an error.  Let's hope this works this time.
     -- --------------------------------------------------------------------

     return false,self.__ctx:error()

   elseif bytes == tls.WANT_INPUT then
     self.__resume = true
     coroutine.yield()
     return self:_drain(data)

   elseif bytes == tls.WANT_OUTPUT then
     nfl.SOCKETS:update(conn,"rw")
     self.__resume = true
     coroutine.yield()
     return self:_drain(data)

   elseif bytes < #data then
     nfl.SOCKETS:update(conn,"rw")
     self.__resume = true
     coroutine.yield()
     return self:_drain(data:sub(bytes+1,-1))
   end

   return true
 end
-----[ END OF LINE ]-----

Now, upon receiving a tls.WANT_OUTPUT it updates the events on the underlying
socket descriptor from “read ready” (which is always true) to “read and write
ready.” But even that didn't fix the issue.

I then spent the time trying to determine the threshhold, creating files of
various sizes until I got two that differed by just one byte. Any file that
has 11,466 bytes or less will get served up. Any file that is 11,467 bytes or
more, the connection is closed with the error “Resource temporarily
unavailable.” I have yet to figure out the cause of that. Weird.

[1] https://github.com/spc476/GLV-1.12556
[2] https://github.com/spc476/lua-conmanorg/blob/master/src/tls.c
[3] gopher://gopher.conman.org/0Phlog:2018/07/19.1
[4] gopher://zaibatsu.circumlunar.space:70/0/~solderpunk/gemini/docs/spec-spec.txt
[5] gemini://gemini.conman.org/

Email author at [email protected]