It would be nice if an app already has an existing FD (via usocket, cl+ssl, etc) to be able to wrap it in a cl-async socket.
Also need ability to wrap existing SSL fd.
This seems to work for bare sockets. SSL will probably be a bit more involved.
(defun wrap-existing-fd (new-fd)
"Given an existing file descriptor, wraps it in a cl-async socket, ready for
monitoring by libevent."
(let* ((socket (as:tcp-connect "127.0.0.1" 1 (lambda (sock data) nil) (lambda (ev) nil)))
(bufferevent (as:socket-c socket))
(fd (le:bufferevent-getfd bufferevent)))
;; close the temporary socket
;; set the new fd into the bufferevent
(le:bufferevent-setfd bufferevent new-fd)
;; this socket now wraps the new fd
Done, turns out libevent had this ability all along, not many changes needed at all. tcp-connect now accepts an :fd arg, which can be used to pass in an existing file descriptor.
Here's a simple function to get an fd from a usocket socket object on a few lisps (inspired by cl+ssl's stream-fd method). Note that this is not included in cl-async, so will have to be a utility function in whatever app needs it:
(defun get-usocket-fd (connection)
"Gets the fd from a usocket connection."
(let* ((type (type-of connection))
(stream (cond ((subtypep type 'usocket:stream-usocket)
((subtypep type 'stream)
(ccl::ioblock-device (ccl::stream-ioblock stream t))
This handles simple TCP sockets in cl-async, but not SSL sockets. There is now an issue open for that item as well: issue #43.
Thanks @orthecreedence this looks great. I'm going to test this ASAP.
One suggestion reading the implementation, it's likely that it would be more clear if you'd split the tcp-connect function in two function, one being the low-level plugin of the fd into libevent, the other one doing the connect.
This would allow guys like me to not overlook tcp-connect because the name implies connect whereas the socket is already connected, and all is interesting here it the fd (whatever it's a socket or a file or anything else).
Very good suggestion. I'll create a lower-level init-connection function (name not set in stone) that inits a socket object and then have tcp-connect connect it. I'd like to not make breaking changes to tcp-connect if I can avoid it, so it might end up being a keyword parameter, but if it starts getting too convoluted I might split things up more. Just depends how it looks when I finish =].
Note, I create a new issue for this (issue #45)