parent
ba8b669dae
commit
782aa78d56
@ -0,0 +1,12 @@
|
||||
|
||||
|
||||
(asdf:defsystem #:cl-sipc
|
||||
:description "AF_UNIX IPC for CL"
|
||||
:author "Avril <flanchan@cumallover.me>"
|
||||
:license "None"
|
||||
:version "0.0.1"
|
||||
:serial t
|
||||
:depends-on ( :cffi )
|
||||
:components ((:file "package")
|
||||
(:file "ffi")
|
||||
(:file "cl-sipc")))
|
@ -0,0 +1,42 @@
|
||||
;; cl-sipc
|
||||
|
||||
(in-package :cl-sipc)
|
||||
|
||||
(defparameter *on-error* #'(lambda (err) nil))
|
||||
(defparameter *on-message* #'(lambda (msg)
|
||||
(not (eql :close (car msg)))))
|
||||
|
||||
;; wrappers
|
||||
|
||||
(defun bind (file)
|
||||
"bind to the AF_UNIX socket `file'"
|
||||
"returns the sd on success, nil on failure"
|
||||
"(remember it has to be deleted first!)"
|
||||
(let ((rc (si-bind file)))
|
||||
(if (< rc 0) ;error
|
||||
nil
|
||||
rc)))
|
||||
|
||||
(defun hook (sd on-err on-msg)
|
||||
"listen on socket `sd'"
|
||||
"on error call the callback `on-err' with args (error)"
|
||||
"on message call the callback `on-msg' with args (type message)"
|
||||
"type can be:
|
||||
:string - a string
|
||||
:binary - (TODO) a foreign pointer
|
||||
:close - a close request"
|
||||
"returns rc on success (1), and nil on failure"
|
||||
"(note: this function blocks until the connection closes)"
|
||||
(let ((*on-message* on-msg)
|
||||
(*on-err* on-err))
|
||||
(let ((rc (si-listen sd (callback si-error-callback) (callback si-callback))))
|
||||
(if (< rc 0)
|
||||
nil
|
||||
rc))))
|
||||
|
||||
(defun release (sd)
|
||||
"close a socket `sd'"
|
||||
(si-close sd)
|
||||
t)
|
||||
|
||||
(mapc #'export '(bind hook release))
|
@ -0,0 +1,76 @@
|
||||
;; Foreign functions
|
||||
|
||||
(in-package :cl-sipc)
|
||||
|
||||
|
||||
(defctype si-type :int)
|
||||
(defconstant +si-string+ 0)
|
||||
(defconstant +si-binary+ 1)
|
||||
(defconstant +si-close+ 2)
|
||||
|
||||
(defctype si-error :int)
|
||||
(defconstant +sie-accept+ 0)
|
||||
(defconstant +sie-read+ 1)
|
||||
(defconstant +sie-pconcls+ 2)
|
||||
(defconstant +sie-invalid+ 3)
|
||||
|
||||
(defctype si-send-rc :int)
|
||||
(defconstant +si-send-okay+ 0)
|
||||
(defconstant +si-send-partial+ 1)
|
||||
(defconstant +si-send-error+ -1)
|
||||
(defconstant +si-send-failure+ -2)
|
||||
|
||||
;; library definition
|
||||
|
||||
(define-foreign-library libsipc
|
||||
(:unix (:or "libsipc.so" "libsipc-ffi.so" "./libsipc.so"))
|
||||
(t (:default "libsipc")))
|
||||
|
||||
(use-foreign-library libsipc)
|
||||
|
||||
;; FFI helper functions
|
||||
|
||||
(defcfun "sif_type" si-type (message :pointer))
|
||||
(defcfun "sif_size" :unsigned-int (message :pointer))
|
||||
(defcfun "sif_data" :pointer (message :pointer))
|
||||
|
||||
(defcfun "si_error_string" :pointer (err si-error))
|
||||
|
||||
;; Callbacks
|
||||
|
||||
(defun marshal-ec (err)
|
||||
(cond ((= err #.+sie-accept+) :accept)
|
||||
((= err #.+sie-read+) :read)
|
||||
((= err #.+sie-pconcls+) :closed)
|
||||
((= err #.+sie-invalid+) :message)
|
||||
(t :unknown)))
|
||||
|
||||
(defcallback si-error-callback :int ((err si-error))
|
||||
(when (symbol-value '*on-error*)
|
||||
(if (funcall (symbol-value '*on-error*) (marshal-ec err))
|
||||
0
|
||||
1)))
|
||||
|
||||
(defcallback si-callback :int ((message :pointer))
|
||||
(let* ((type (sif-type message))
|
||||
(size (sif-size message))
|
||||
(data (sif-data message))
|
||||
(rval (cond ((= type #.+si-string+) (funcall (symbol-value '*on-message*) :string (foreign-string-to-lisp data)))
|
||||
((= type #.+si-close+) (funcall (symbol-value '*on-message*) :close nil))
|
||||
((= type #.+si-binary+) (funcall (symbol-value '*on-message*) :binary data)))))
|
||||
(if rval
|
||||
0
|
||||
1)))
|
||||
|
||||
;; libsipc functions
|
||||
|
||||
(defcfun "si_bind" :int
|
||||
(file :string))
|
||||
|
||||
(defcfun "si_listen" :int
|
||||
(server :int)
|
||||
(on-error :pointer)
|
||||
(on-message :pointer))
|
||||
|
||||
(defcfun "si_close" :void
|
||||
(server :int))
|
@ -0,0 +1,18 @@
|
||||
#include <sipc.h>
|
||||
|
||||
//Some FFI helpers
|
||||
|
||||
si_type sif_type(const si_message* msg)
|
||||
{
|
||||
return msg->type;
|
||||
}
|
||||
|
||||
unsigned int sif_size(const si_message* msg)
|
||||
{
|
||||
return msg->data_len;
|
||||
}
|
||||
|
||||
const unsigned char* sif_data(const si_message* msg)
|
||||
{
|
||||
return msg->data;
|
||||
}
|
@ -0,0 +1,5 @@
|
||||
|
||||
|
||||
(defpackage #:cl-sipc
|
||||
(:use #:cl
|
||||
#:cffi))
|
@ -0,0 +1,19 @@
|
||||
|
||||
|
||||
(ql:quickload :cl-sipc)
|
||||
|
||||
(defparameter *socket-file* "sipc.socket")
|
||||
(defparameter *socket* (cl-sipc:bind *socket-file*))
|
||||
|
||||
(when (not *socket*)
|
||||
(format t "Error binding ~a~%" *socket-file*) (quit))
|
||||
|
||||
(let ((rc (cl-sipc:hook *socket*
|
||||
#'(lambda (err)
|
||||
(format t "Error: ~a~%" err)
|
||||
nil)
|
||||
#'(lambda (type message)
|
||||
(format t "<- (~a) ~a~%" type message)
|
||||
(not (eql :close type))))))
|
||||
(format t "Listen rc ~a~%" rc)
|
||||
(cl-sipc:release *socket*))
|
Loading…
Reference in new issue