lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


Hmm.  Bleh, I'd be beating a dead horse if I went on about the security thing.

Anyway, I went with copying socket objects into fd sets from tables and back again because as it was explained to me several times in both tutorials and from other programmers, select() is only efficient for a small number of FDs.  I thought: What's the point of trying to be efficient about how I pass a collection of sockets to select() when select() isn't the most efficient polling interface?  I only made a binding to select() because the prep work was much simpler than trying to understand how to set up epoll()  That got me into looking at lua-ev and how that library also expects to receive Lua file handles (which was great!).  I helped the author there update to 5.2 but then I realized that lua-ev is a wrapper over libev, which is only level-triggered and not edge-triggered.  So now I am looking at a libevent binding..

Had a bunch of people try to talk me into the zmq bindings or into using some other framework.  Apparently ZMQ is very friendly, and then the other framework I can't remember the name of wraps ZMQ to do asyncronous event triggering and such.  I just tend to avoid frameworks...

I do cover IPv4 and IPv6 in my socket bindings, and then I allow for packing the struct as a sockaddr structure, or a sockaddr_un...  I don't personally know how to do Bluetooth by building raw packets but I left the ability in there for the pack_sockaddr() function... (I think)  I mean infrared and bluetooth are somewhat used... NFC must be possible that way.  I need to learn more about networking with raw sockets.

I believe the code for sending to a UDP socket looked like this -- it's been a few months since I did it so it may be wrong...

local lsock = require('lsock')
local c = assert(lsock.socket(lsock.AF_INET, lsock.SOCK_DGRAM))
local sa = lsock.pack_sockaddr { sin_family = lsock.AF_INET, sin_port = 5000, sin-addr = '127.0.0.0' }

-- I know this looks strange, as UDP connections don't handshake, but from
-- what I remember it associates the sockaddr with the socket in Linux' networking stack
-- this is how you can send() on a UDP socket rather than needing sendto()
lsock.connect(c, sa)

c:write("hello there")
c:flush()

assert(lsock.close(c))

---------------------------

I don't know if this works and I'm afraid to try it :(  Perhaps I was very full of shit when I said it worked.  It should be possible... sockets are just fd's on Linux, but I know it's possible to associate the sockaddr info with the fd so you can fwrite() to the fd and I believe it's with connect() -- not just for connection-oriented sockets.

Anyway, ciao ciao all :]

On Sat, Nov 16, 2013 at 1:07 AM, Sean Conner <sean@conman.org> wrote:
It was thus said that the Great Sir Pogsalot once stated:
> In response to Coda:
>
> I don't agree that opening up file handle creation to the C side of Lua
> would mean we have to forgo an appropriate level of security.  Lua does
> have a fair bit of type checking code to make sure its receiving file
> handles in the io library... The easiest way to fool it is to take any
> userdata you want and set the metatable to the "FILE*" table in the
> registry -- if you use the right io function you can cause a segfault if it
> looks at non-existent members of the userdata.  This would be easier in Lua
> 5.1 because you have newproxy() to create a zero-sized userdata. :-)  Still
> -- *SECURITY* :D

  It's one thing to try to subvert security through a program, and
subverting security through a library.  In the former, yes, I would expect a
program not to trust much coming from the "outside world" and do quite a bit
of validation.  On the later, that's like having physical access to a
computer---it's game out and no amount of checking paremeters will save you.
I, like Coda, have decided to trust the programmer [1].

> In response to Sean:
>
> Unfortunately I am not too familiar with the ins and outs of using poll()
> or epoll() -- select() was the simplest for me to grasp and I did that by
> copying fd sets into tables and back.  Don't have much more to say about
> that...  :x

  All three do the same thing---tell you when a file is ready for reading or
writing.  How they go about it is different, but the interface I created at
least abstracts the details away.  I decided against a table approach, since
copying the file descriptors back and forth when calling select() or poll()
could get too expensive (that, and the fact that there's no array to use
with epoll()) and went with explicite calls to insert and remove entries.

> I have actually [successfully] written to a UDP-packeted socket with
> io.write(), but I didn't do more experimenting to see if io.read() worked
> just as well.

  Hmm, I'd like to see the code for this, because until you changed the
buffering to none (:setvbuf('no')) or explicitely flushed the data
(file:flush()) then the data will just accumulate until (by default)
LUAL_BUFFERSIZE (which is BUFSIZ, defined by ANSI C) bytes have been
written (did I mention leaky abstractions?)

> I think I'll go back on what I said about :getfd().  I don't like fds being
> known to the Lua side of things, but a fair number of libraries expect that
> method to exist.  It is somewhat common, but I think it only exists because
> people are representing files as different types (bad).  :>

  It's pervasive because the underlying implemention on quite a few
operating systems is that of file descpriptors, Unix being the most famous,
but it was also used by MS-DOS and by extension, Windows for some time.
There's also a bunch of stuff you can set through ioctl() and fcntl(), as
well as tcgetattr(), tcsetattr(), tcsendbreak(), tcdrain(), tcflush() and
tcflow() (TTY stuff).

> The main focus of my socket bindings is that I was trying to be as true to
> the C prototype as possible so it would be easy for beginners to take a C
> networking tutorial and translate it to Lua without much guessing or
> digging through documentation.  Sometimes I feel like details about
> luasocket are hard to find...

  The details about luasocket can be found in "UNIX Network Programming"
although the authors never talk about Lua.

  I personally, have found myself getting away a bit from a pure mirror of
the C API and have gone more for what, to me, makes more sense in Lua.  I
also concentrate more on IPv4, IPv6 and Unix sockets since basically, that's
all *I* care about (and frankly, in my opinion, those protocols won).

> I like your socket option code in net.c though, it's much friendlier than
> what I tried to do by adding every defined CONSTANT I could and having a
> get/setsockopt().

  Yeah, I like doing:

        socket.reuseaddr = true
        socket.nonblock  = true

  over

        int value = 1;
        setsockopt(socket,SOL_SOCKET,SO_REUSEADDR,&value,sizeof(int));

        value = fcntl(socket,F_GETFL,0);
        value |= O_NONBLOCK;
        fcntl(socket,F_SETFL,value);

> I'm jealous that you got netlua_interfaces() implemented ;-)  I need to
> give lsock similar functionality.  OH THE JOYS OF HAVING YET ANOTHER SOCKET
> LIBRARY :]

  It only works on Linux.  Solaris (the system I use at work) does not have
(or I have not found yet) that, and I haven't tried Mac OS-X yet.

  -spc

[1]     Such that if you pass in a NULL pointer, my library *will* segfault
        [2].  I operate under the "garbage in, garbage out" principle, or
        rather, "give me valid data, and I will return you valid data."

        See

        https://github.com/spc476/SPCDNS/blob/master/src/codec.c

        for an example of this.

[2]     That is, if you disable assert().