AF_UNIX socket IPC for Common Lisp.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
Avril f0f00f4c7e
2
3 years ago
libsipc packing for GCC 4 years ago
tools proper signing, added ignorable/recoverable error 4 years ago
.gitignore easier testing 4 years ago
Makefile server can send responses 4 years ago
README proper signing, added ignorable/recoverable error 4 years ago
cl-sipc.asd proper signing, added ignorable/recoverable error 4 years ago
cl-sipc.lisp fucking weird bug where it overwrites cffi functions????? 3 years ago
ffi.lisp 2 3 years ago
libsipc.so whoops 4 years ago
package.lisp fucking weird bug where it overwrites cffi functions????? 3 years ago
pointer.lisp fucking weird bug where it overwrites cffi functions????? 3 years ago
test-client move tests 4 years ago
test-server move tests 4 years ago

README

cl-sipc (common lisp socket inter-process communication)

Unix domain socket message passing for Common Lisp.

Run `make' in this directory once to build the CFFI library.
Run `sudo make install-ffi' to install the ffi library system-wide. (`sudo make uninstall-ffi' to remove)

The symlinked libsipc.so will resolve after the ffi library is built and the package will work in this directory (the symlink is to libsipc/libsipc-ffi.so)
Additionally you can run `sudo make install-ffi' to make it work system-wide (installed to /usr/lib/libsipc.so) (`sudo make uninstall-ffi' to remove it)
Or you can copy/symlink libsipc/libsipc-ffi.so to wherever you need.
(see additional installation options below).

Additional tools can be built by running `make all-ffi' in the libsipc/ directory (or `make utils' in this one).

Functions:
;server functions
sipc:bind(file) ;; Bind to socket `file'. Returns the socket descriptor on success and nil on fail (the socket must not already exist)
sipc:timeout(socket sec) ;; Set read timeout (in seconds) to socket. (if value is NIL, nothing happens, if value is 0, set to infinite). (note: when something fails timeout it sends error :MESSAGE (invalid message).
sipc:release(socket) ;; Close socket
sipc:hook(socket error-callback message-callback)
;; start listening on `socket'. error-callback should be in format (lambda (error) ...). message-callback should be in format (lambda (type message )...).
;; available errors are:
; :accept - There was an error accepting the connection
; :read - There was an error reading the message
; :closed - The connection was closed before a message could be read
; :message - The message was invalid or outside the acceptable size bounds (TODO make this runtime instead of compile-time constant)
; :checksum - The message had an invalid checksum
;; there are also ignorable/recoverable errors, which are sent to the error callback as suck '(:warning <error name>). These are treated differently. If the error callback returns T, let the message be carried on. If the error callback returns NIL, discard it. Available ones are:
; (:warning :checksum) - The message had no checksum. (note: if this is not allowed to pass then :CHECKSUM error is raised).
;; (see libsipc/include/sipc.h for more details)
;; available types are:
; :string - Normal string
; :binary - pointer to memory (see struct pointer in `pointer.lisp')
; :close - A request to close (the message is always NIL for this type)
;; If an error or message callback returns NIL, the listener is stopped (you still have to call sipc:release()). Otherwise, the return is ignored.
sipc:respond(message value &optional type) ;; send response (note: only valid when handling message) works the same as send() (see below) with additional error responses:
;; t - success
;; :response-disabled - SI_NORESP flag was set
;; :response-invalid - this message cannnot be responded to like this
;; :response-multi - a response has already been sent
(sipc:with-bound-socket (socket-name socket-filename)
body)
;; Bind socket from `socket-filename' to new lexical variable `socket-name' and run (progn @body), then relase the socket afterwards. If the socket fails to bind, return nil and do not attempt to execute body.
;; Add `:connect' after socket-filename to connect instead of binding.
;client functions
sipc:connect(file) ;; connect to socket `file', returns sd on success, nil on failure.
sipc:send(sd value &ptional type (keep-response t)) ;; send `value' to socket `sd' (optionally specify type (see above types), default :string). returns the response if one was sent, or t if keep-response if nil or the server did not send one.
;; :string -- value expected to be a string
;; :binary --value expected to be `pointer' struct
;; :close -- value ignored
sipc:send-quick(file value &optional type) ;; send `value' to socket file `file'

See `cl-sipc.lisp' for more documentation.

Pointers:
(sipc:make-pointer :memory cffi-pointer :size size) ;; Make from CFFI foreign-pointer with size
(sipc:pointer-free ptr) ;; Free pointer

(sipc:pointer-from-seq sequence &optional cffi-type) ;; make pointer from list or vector
(sipc:pointer-from value &optional cffi-type) ;; make pointer from single value
(sipc:pointer-from-string string) ;; make pointer from lisp string
(sipc:pointer-to-array ptr &optional cffi-type) ;; make vector from elements in ptr
; (note: all cffi-type arguments default to :unsigned-char)

(sipc:with-pointer (name &optional type cffi-type) value body...) ;; allocate pointer from value with type and lexical name. free after body.
;; type:
;; :string -- expects Lisp string
;; :sequence -- expects list or vector
;; :single -- expects single value
;; :infer (defualt) -- infer from value
;; optionally specify cffi type (default :unsigned-char)
(see pointer.lisp for more info)

---

Other installation options

Run `sudo make install' to install ffi library system-wide and attempt to symlink to ~/quicklisp/local-projects/cl-sipc (if it exists). Or run `sudo make install-ffi' to just install the library. (note: you can run `make install' without sudo, in which case it will just attempt to symlink and not install the library. the same is true for `make uninstall'.)
-> sudo make install ;; install ffi systemwide and symlink
-> make install ;; only symlink
-> sudo make install-ffi ;; insall only ffi
-> sudo make uninstall ;; uninstall ffi systemwide and remove symlink
-> make uninstall ;; only remove symlink
-> sudo make uninstall-ffi ;; only uninstall ffi

---

Example using test-client.lisp && test-server.lisp:

Terminal 1:
$ ./test-server

Terminal 2:
$ ./test-client
> (send "Hello world")

Terminal 1:
<- (STRING) Hello world

Terminal 2:
> (close)

Terminal 1:
<- (CLOSE) NIL
[-] listen rc 1
$

Terminal 1:
> quit
$

Example using sipcli (run `make all-ffi' in libsipc/ directory)
(see `test-server.lisp' for example server)

Terminal 1:
[user@host cl-sipc]$ ./test-server
-> [+] listening on sipc.socket...

Terminal 2:
[user@host libsipc]$ ./sipcli -p ../sipc.socket "Hello World"

Terminal 1:
<- (STRING) Hello World

Terminal 2:
[user@host libsipc]$ ./sipcli -cf ../sipc.socket

Terminal 1:
<- (CLOSE) NIL
[-] listen rc 1
[user@host cl-sipc]$

---

TODO: Internal error handling.
TODO: Have libsipc built on system load
TODO: better .so loading