1.1--- a/demo.asd Mon Jun 05 19:59:26 2023 -0400
1.2+++ b/demo.asd Tue Jun 06 18:55:17 2023 -0400
1.3@@ -1,41 +1,25 @@
1.4 ;;; demo.asd
1.5 (in-package #:asdf-user)
1.6
1.7+(defsystem "demo/sys"
1.8+ :components ((:file "src/package")))
1.9+
1.10 (defsystem "demo"
1.11 :version "0.1.0"
1.12 :author "ellis <ellis@rwest.io>"
1.13 :maintainer "ellis <ellis@rwest.io>"
1.14 :description ""
1.15 :homepage "https://rwest.io/p/demo"
1.16- :bug-tracker "https://gitlab.rwest.io/ellis/demo/issues"
1.17- :source-control (:hg "https://gitlab.rwest.io/ellis/demo")
1.18+ :bug-tracker "https://lab.rwest.io/otom8/demo/issues"
1.19+ :source-control (:hg "https://lab.rwest.io/otom8/demo")
1.20 :license "WTFPL"
1.21- :depends-on ("demo/sys" "demo/db" "demo/ui" "demo/cli")
1.22+ :depends-on ("demo/sys" :cl-dbi :sxql :log4cl :verbose :bordeaux-threads :clingon :clog)
1.23 :in-order-to ((test-op (test-op "src/test")))
1.24 :build-pathname "demo")
1.25
1.26-(defsystem "demo/sys"
1.27- :depends-on (:sxql :log4cl)
1.28- :components ((:file "src/packages")
1.29- (:module "tk"
1.30- :pathname "src/tk"
1.31- :serial t
1.32- :components ((:file "tk")
1.33- (:file "rs" :depends-on ("tk"))))))
1.34-
1.35 (defmethod perform :after ((op load-op) (c (eql (find-system :demo))))
1.36 (pushnew :demo *features*))
1.37
1.38-(defsystem "demo/cli"
1.39- :depends-on (:clingon "demo/sys" "demo/ui" "demo/db")
1.40- :components ((:file "src/cli")))
1.41-(defsystem "demo/ui"
1.42- :depends-on (:clog "demo/sys" "demo/db")
1.43- :components ((:file "src/ui")))
1.44-(defsystem "demo/db"
1.45- :depends-on (:cl-dbi "demo/sys")
1.46- :components ((:file "src/db")))
1.47-
1.48 (defsystem "demo/tests"
1.49 :depends-on ("demo" "fiveam")
1.50 :components ((:module "src/tests"
2.1--- a/readme.org Mon Jun 05 19:59:26 2023 -0400
2.2+++ b/readme.org Tue Jun 06 18:55:17 2023 -0400
2.3@@ -6,11 +6,12 @@
2.4 * How it works
2.5 The backend services are written in Rust and controlled by a simple
2.6 messaging protocol. Services provide common runtime capabilities known
2.7-as the /core protocol/ but are specialized on a unique /service type/
2.8-which may in turn register their own /custom protocols/ (via core).
2.9+as the /service protocol/ but are specialized on a unique /service
2.10+type/ which may in turn register their own /custom protocols/ (via
2.11+core).
2.12
2.13 Services are capable of dispatching data directly to clients, or
2.14-storing data in the /database/ (TBD).
2.15+storing data in the /database/ (sqlite, postgres, mysql).
2.16
2.17 The frontend clients are pre-dominantly written in Common Lisp and
2.18 come in many shapes and sizes. There is a cli-client, web-client
2.19@@ -20,6 +21,9 @@
2.20 * Guide
2.21 ** Build
2.22 - *install dependencies*
2.23+ #+begin_src bash
2.24+ ./tools/deps.sh
2.25+ #+end_src
2.26 - Rust =curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh=
2.27 - Common Lisp
2.28 - on Linux ::
3.1--- a/src/build.rs Mon Jun 05 19:59:26 2023 -0400
3.2+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
3.3@@ -1,17 +0,0 @@
3.4-use std::env;
3.5-use std::fs::create_dir;
3.6-use std::path::PathBuf;
3.7-fn main() {
3.8- let crate_dir: PathBuf = env::var("CARGO_MANIFEST_DIR")
3.9- .expect("CARGO_MANIFEST_DIR env var is not defined")
3.10- .into();
3.11- // let mpk_py = "build.py";
3.12- let build_dir = crate_dir.join("ffi/");
3.13- if !build_dir.exists() {
3.14- create_dir(&build_dir).unwrap();
3.15- }
3.16- cbindgen::generate(crate_dir)
3.17- .expect("Unable to find cbindgen.toml configuration file")
3.18- .write_to_file(build_dir.join("demo.h"));
3.19-
3.20-}
4.1--- a/src/cbindgen.toml Mon Jun 05 19:59:26 2023 -0400
4.2+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
4.3@@ -1,14 +0,0 @@
4.4-include_guard = "demo_h"
4.5-autogen_warning = "/* DO NOT TOUCH */"
4.6-include_version = true
4.7-language = "C"
4.8-cpp_compat = true
4.9-line_length = 88
4.10-documentation = true
4.11-[parse]
4.12-parse_deps = true
4.13-include = ["obj","fig","libc"]
4.14-extra_bindings = ["obj","fig","libc"]
4.15-#expand = ["demo","obj"]
4.16-#[parse.expand]
4.17-#crates = ["demo"]
4.18\ No newline at end of file
5.1--- a/src/db/db.lisp Mon Jun 05 19:59:26 2023 -0400
5.2+++ b/src/db/db.lisp Tue Jun 06 18:55:17 2023 -0400
5.3@@ -1,197 +1,1 @@
5.4-(in-package :demo)
5.5-
5.6-(define-foreign-library rocksdb
5.7- (:win32 "rocksdb")
5.8- (t (:default "librocksdb")))
5.9-
5.10-(use-foreign-library rocksdb)
5.11-
5.12-(defcfun ("rocksdb_options_create" create-options) :pointer)
5.13-(defcfun ("rocksdb_options_destroy" destroy-options) :void (options :pointer))
5.14-(defcfun ("rocksdb_options_increase_parallelism" increase-parallelism) :void (opt :pointer) (total-threads :int))
5.15-(defcfun ("rocksdb_options_optimize_level_style_compaction" optimize-level-style-compaction) :void (opt :pointer) (memtable_memory_budget :uint64))
5.16-(defcfun ("rocksdb_options_set_create_if_missing" set-create-if-missing) :void (opt :pointer) (val :boolean))
5.17-
5.18-(defcfun ("rocksdb_writeoptions_create" create-writeoptions) :pointer)
5.19-(defcfun ("rocksdb_writeoptions_destroy" destroy-writeoptions) :void (opt :pointer))
5.20-(defcfun ("rocksdb_readoptions_create" create-readoptions) :pointer)
5.21-(defcfun ("rocksdb_readoptions_destroy" destroy-readoptions) :void (opt :pointer))
5.22-
5.23-(defcfun ("rocksdb_open" open-db*) :pointer (opt :pointer) (name :string) (errptr :pointer))
5.24-(defcfun ("rocksdb_close" close-db) :void (opt :pointer))
5.25-(defcfun ("rocksdb_cancel_all_background_work" cancel-all-background-work) :void (db :pointer) (wait :boolean))
5.26-
5.27-(defcfun ("rocksdb_put" put*) :void (db :pointer) (options :pointer) (key :pointer) (keylen :unsigned-int) (val :pointer) (vallen :unsigned-int) (errptr :pointer))
5.28-(defcfun ("rocksdb_get" get*) :pointer (db :pointer) (options :pointer) (key :pointer) (keylen :unsigned-int) (vallen :pointer) (errptr :pointer))
5.29-
5.30-(defcfun ("rocksdb_create_iterator" create-iter*) :pointer (db :pointer) (opt :pointer))
5.31-(defcfun ("rocksdb_iter_destroy" destroy-iter) :void (iter :pointer))
5.32-(defcfun ("rocksdb_iter_seek_to_first" move-iter-to-first) :void (iter :pointer))
5.33-(defcfun ("rocksdb_iter_valid" valid-iter-p) :boolean (iter :pointer))
5.34-(defcfun ("rocksdb_iter_next" move-iter-forward) :void (iter :pointer))
5.35-(defcfun ("rocksdb_iter_prev" move-iter-backward) :void (iter :pointer))
5.36-(defcfun ("rocksdb_iter_key" iter-key*) :pointer (iter :pointer) (klen-ptr :pointer))
5.37-(defcfun ("rocksdb_iter_value" iter-value*) :pointer (iter :pointer) (vlen-ptr :pointer))
5.38-
5.39-(define-condition unable-to-open-db (error)
5.40- ((db-path :initarg :db-path
5.41- :reader db-path)
5.42- (error-message :initarg :error-message
5.43- :reader error-message)))
5.44-
5.45-(defmethod print-object ((obj unable-to-open-db) stream)
5.46- (print-unreadable-object (obj stream :type t :identity t)
5.47- (format stream "error-message=~A" (error-message obj))))
5.48-
5.49-(define-condition unable-to-put-key-value-to-db (error)
5.50- ((db :initarg :db
5.51- :reader db)
5.52- (key :initarg :key
5.53- :reader key)
5.54- (val :initarg :val
5.55- :reader val)
5.56- (error-message :initarg :error-message
5.57- :reader error-message)))
5.58-
5.59-(define-condition unable-to-get-value-to-db (error)
5.60- ((db :initarg :db
5.61- :reader db)
5.62- (key :initarg :key
5.63- :reader key)
5.64- (error-message :initarg :error-message
5.65- :reader error-message)))
5.66-
5.67-(defun open-db (db-path &optional opt)
5.68- (unless opt
5.69- (setq opt (create-options)))
5.70- (let ((errptr (foreign-alloc :pointer)))
5.71- (setf (mem-ref errptr :pointer) (null-pointer))
5.72- (let* ((db-path (if (pathnamep db-path)
5.73- (namestring db-path)
5.74- db-path))
5.75- (db (open-db* opt db-path errptr))
5.76- (err (mem-ref errptr :pointer)))
5.77- (unless (null-pointer-p err)
5.78- (error 'unable-to-open-db
5.79- :db-path db-path
5.80- :error-message (foreign-string-to-lisp err)))
5.81- db)))
5.82-
5.83-(defmacro clone-octets-to-foreign (lisp-array foreign-array)
5.84- (let ((i (gensym)))
5.85- `(loop for ,i from 0 below (length ,lisp-array)
5.86- do (setf (mem-aref ,foreign-array :unsigned-char ,i)
5.87- (aref ,lisp-array ,i)))))
5.88-
5.89-(defmacro clone-octets-from-foreign (foreign-array lisp-array len)
5.90- (let ((i (gensym)))
5.91- `(loop for ,i from 0 below ,len
5.92- do (setf (aref ,lisp-array ,i)
5.93- (mem-aref ,foreign-array :unsigned-char ,i)))))
5.94-
5.95-(defun put-kv (db key val &optional opt)
5.96- (unless opt
5.97- (setq opt (create-writeoptions)))
5.98- (with-foreign-objects ((errptr :pointer)
5.99- (key* :unsigned-char (length key))
5.100- (val* :unsigned-char (length val)))
5.101- (clone-octets-to-foreign key key*)
5.102- (clone-octets-to-foreign val val*)
5.103- (setf (mem-ref errptr :pointer) (null-pointer))
5.104- (put* db
5.105- opt
5.106- key*
5.107- (length key)
5.108- val*
5.109- (length val)
5.110- errptr)
5.111- (let ((err (mem-ref errptr :pointer)))
5.112- (unless (null-pointer-p err)
5.113- (error 'unable-to-put-key-value-to-db
5.114- :db db
5.115- :key key
5.116- :val val
5.117- :error-message (foreign-string-to-lisp err))))))
5.118-
5.119-(defun put-kv-str (db key val &optional opt)
5.120- (let ((key-octets (babel:string-to-octets key))
5.121- (val-octets (babel:string-to-octets val)))
5.122- (put-kv db key-octets val-octets opt)))
5.123-
5.124-(defun get-kv (db key &optional opt)
5.125- (unless opt
5.126- (setq opt (create-readoptions)))
5.127-
5.128- (with-foreign-objects ((val-len-ptr :unsigned-int)
5.129- (errptr :pointer)
5.130- (key* :unsigned-char (length key)))
5.131- (clone-octets-to-foreign key key*)
5.132- (setf (mem-ref errptr :pointer) (null-pointer))
5.133- (let ((val (get* db
5.134- opt
5.135- key*
5.136- (length key)
5.137- val-len-ptr
5.138- errptr)))
5.139- (let ((err (mem-ref errptr :pointer)))
5.140- (unless (null-pointer-p err)
5.141- (error 'unable-to-get-value-to-db
5.142- :db db
5.143- :key key
5.144- :error-message (foreign-string-to-lisp err)))
5.145-
5.146- (unless (null-pointer-p val)
5.147- (let* ((val-len (mem-ref val-len-ptr :unsigned-int))
5.148- (val* (make-array val-len
5.149- :element-type '(unsigned-byte 8))))
5.150- (clone-octets-from-foreign val val* val-len)
5.151- val*))))))
5.152-
5.153-(defun get-kv-str (db key &optional opt)
5.154- (let ((key-octets (babel:string-to-octets key)))
5.155- (let ((#1=val-octets (get-kv db key-octets opt)))
5.156- (when #1#
5.157- (babel:octets-to-string #1#)))))
5.158-
5.159-(defun create-iter (db &optional opt)
5.160- (unless opt
5.161- (setq opt (create-readoptions)))
5.162- (create-iter* db opt))
5.163-
5.164-(defun iter-key (iter)
5.165- (with-foreign-objects ((klen-ptr :unsigned-int))
5.166- (setf (mem-ref klen-ptr :unsigned-int) 0)
5.167- (let* ((key-ptr (iter-key* iter klen-ptr))
5.168- (klen (mem-ref klen-ptr :unsigned-int))
5.169- (key (make-array klen :element-type '(unsigned-byte 8))))
5.170- (clone-octets-from-foreign key-ptr key klen)
5.171- key)))
5.172-
5.173-(defun iter-key-str (iter)
5.174- (let ((#1=key-octets (iter-key iter)))
5.175- (when #1#
5.176- (babel:octets-to-string #1#))))
5.177-
5.178-(defun iter-value (iter)
5.179- (with-foreign-objects ((len-ptr :unsigned-int))
5.180- (setf (mem-ref len-ptr :unsigned-int) 0)
5.181- (let* ((value-ptr (iter-value* iter len-ptr))
5.182- (vlen (mem-ref len-ptr :unsigned-int))
5.183- (value* (make-array vlen :element-type '(unsigned-byte 8))))
5.184- (clone-octets-from-foreign value-ptr value* vlen)
5.185- value*)))
5.186-
5.187-(defun iter-value-str (iter)
5.188- (let ((#1=val-octets (iter-value iter)))
5.189- (when #1#
5.190- (babel:octets-to-string #1#))))
5.191-
5.192-(defmacro with-open-db ((db-var db-path &optional opt) &body body)
5.193- `(let ((,db-var (open-db ,db-path ,opt)))
5.194- (unwind-protect (progn ,@body)
5.195- (close-db ,db-var))))
5.196-
5.197-(defmacro with-iter ((iter-var db &optional opt) &body body)
5.198- `(let ((,iter-var (create-iter ,db ,opt)))
5.199- (unwind-protect (progn ,@body)
5.200- (destroy-iter ,iter-var))))
5.201+(in-package :demo-db)
6.1--- a/src/gen.rs Mon Jun 05 19:59:26 2023 -0400
6.2+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
6.3@@ -1,84 +0,0 @@
6.4-//! demo
6.5-pub use fig::*;
6.6-pub use obj::*;
6.7-use std::ffi::{CStr, CString}; //OsStr,Path
6.8- //use std::os::unix::ffi::OsStrExt;
6.9-use std::slice;
6.10-use libc::{c_char,size_t};
6.11-
6.12-#[macro_export]
6.13-macro_rules! cdefn {
6.14- (free $t:tt $n:tt) => {
6.15- #[no_mangle]
6.16- pub unsafe extern "C" fn $n(ptr: *mut $t) {
6.17- if ptr.is_null() {
6.18- return;
6.19- }
6.20- let _ = Box::from_raw(ptr);
6.21- }
6.22- };
6.23- (from_string $t:tt $n:tt) => {
6.24- #[no_mangle]
6.25- pub unsafe extern "C" fn $n(ptr: *const c_char) -> *mut $t {
6.26- assert!(!ptr.is_null());
6.27- let p = CStr::from_ptr(ptr).to_str().unwrap();
6.28- Box::into_raw(Box::new(p.into()))
6.29- }
6.30- };
6.31- (json_string $t:tt $r:tt $w:tt) => {
6.32- #[no_mangle]
6.33- pub unsafe extern "C" fn $r(ptr: *const c_char) -> *mut $t {
6.34- assert!(!ptr.is_null());
6.35- let s = CStr::from_ptr(ptr);
6.36- Box::into_raw(Box::new($t::from_json_str(&s.to_str().unwrap()).unwrap()))
6.37- }
6.38-
6.39- #[no_mangle]
6.40- pub unsafe extern "C" fn $w(ptr: *const $t) -> *mut c_char {
6.41- let p = &*ptr;
6.42- let x = p.to_json_string().unwrap();
6.43- CString::new(x.as_str().as_bytes()).unwrap().into_raw()
6.44- }
6.45- };
6.46- (ron_string $t:tt $r:tt $w:tt) => {
6.47- #[no_mangle]
6.48- pub unsafe extern "C" fn $r(ptr: *const c_char) -> *mut $t {
6.49- assert!(!ptr.is_null());
6.50- let s = CStr::from_ptr(ptr);
6.51- Box::into_raw(Box::new($t::from_ron_str(&s.to_str().unwrap()).unwrap()))
6.52- }
6.53-
6.54- #[no_mangle]
6.55- pub unsafe extern "C" fn $w(ptr: *const $t) -> *mut c_char {
6.56- let p = &*ptr;
6.57- let x = p.to_ron_string().unwrap();
6.58- CString::new(x.as_str().as_bytes()).unwrap().into_raw()
6.59- }
6.60- };
6.61- (bytes $t:tt $r:tt $w:tt) => {
6.62- #[no_mangle]
6.63- pub unsafe extern "C" fn $r(ptr: *const u8, len: size_t) -> *mut $t {
6.64- Box::into_raw(Box::new($t::decode(slice::from_raw_parts(ptr,len)).unwrap()))
6.65- }
6.66-
6.67- #[no_mangle]
6.68- pub unsafe extern "C" fn $w(ptr: *const $t) -> *mut u8 {
6.69- let p = &*ptr;
6.70- let mut x = p.encode().unwrap();
6.71- let r = x.as_mut_ptr();
6.72- std::mem::forget(x);
6.73- r
6.74- }
6.75- }
6.76-}
6.77-
6.78-cdefn!(free Service free_service);
6.79-cdefn!(from_string Service service_from_string);
6.80-cdefn!(json_string Service service_from_json_string service_to_json_string);
6.81-cdefn!(ron_string Service service_from_ron_string service_to_ron_string);
6.82-cdefn!(bytes Service service_decode service_encode);
6.83-cdefn!(free CustomService free_custom_service);
6.84-cdefn!(from_string CustomService custom_service_from_string);
6.85-cdefn!(json_string CustomService custom_service_from_json_string custom_service_to_json_string);
6.86-cdefn!(ron_string CustomService custom_service_from_ron_string custom_service_to_ron_string);
6.87-cdefn!(bytes CustomService custom_service_decode custom_service_encode);
7.1--- a/src/lib.rs Mon Jun 05 19:59:26 2023 -0400
7.2+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
7.3@@ -1,117 +0,0 @@
7.4-//! demo/lib.rs --- generated by DEMO:RS-MACROEXPAND
7.5-extern crate libc;
7.6-extern crate obj;
7.7-use libc::{c_char, size_t};
7.8-use obj::{CustomService, Objective, Service};
7.9-use std::ffi::{CStr, CString};
7.10-use std::slice;
7.11-#[no_mangle]
7.12-pub unsafe extern "C" fn free_service(ptr: *mut Service) {
7.13- if ptr.is_null() {
7.14- return;
7.15- }
7.16- let _ = Box::from_raw(ptr);
7.17-}
7.18-#[no_mangle]
7.19-pub unsafe extern "C" fn service_from_string(ptr: *const c_char) -> *mut Service {
7.20- assert!(!ptr.is_null());
7.21- let p = CStr::from_ptr(ptr).to_str().unwrap();
7.22- Box::into_raw(Box::new(p.into()))
7.23-}
7.24-#[no_mangle]
7.25-pub unsafe extern "C" fn service_from_json_string(ptr: *const c_char) -> *mut Service {
7.26- assert!(!ptr.is_null());
7.27- let s = CStr::from_ptr(ptr);
7.28- Box::into_raw(Box::new(
7.29- Service::from_json_str(&s.to_str().unwrap()).unwrap(),
7.30- ))
7.31-}
7.32-#[no_mangle]
7.33-pub unsafe extern "C" fn service_to_json_string(ptr: *const Service) -> *mut c_char {
7.34- let p = &*ptr;
7.35- let x = p.to_json_string().unwrap();
7.36- CString::new(x.as_str().as_bytes()).unwrap().into_raw()
7.37-}
7.38-#[no_mangle]
7.39-pub unsafe extern "C" fn service_from_ron_string(ptr: *const c_char) -> *mut Service {
7.40- assert!(!ptr.is_null());
7.41- let s = CStr::from_ptr(ptr);
7.42- Box::into_raw(Box::new(
7.43- Service::from_ron_str(&s.to_str().unwrap()).unwrap(),
7.44- ))
7.45-}
7.46-#[no_mangle]
7.47-pub unsafe extern "C" fn service_to_ron_string(ptr: *const Service) -> *mut c_char {
7.48- let p = &*ptr;
7.49- let x = p.to_ron_string().unwrap();
7.50- CString::new(x.as_str().as_bytes()).unwrap().into_raw()
7.51-}
7.52-#[no_mangle]
7.53-pub unsafe extern "C" fn service_decode(ptr: *const u8, len: size_t) -> *mut Service {
7.54- Box::into_raw(Box::new(
7.55- Service::decode(slice::from_raw_parts(ptr, len)).unwrap(),
7.56- ))
7.57-}
7.58-#[no_mangle]
7.59-pub unsafe extern "C" fn service_encode(ptr: *const Service) -> *mut u8 {
7.60- let p = &*ptr;
7.61- let mut x = p.encode().unwrap();
7.62- let r = x.as_mut_ptr();
7.63- std::mem::forget(x);
7.64- r
7.65-}
7.66-#[no_mangle]
7.67-pub unsafe extern "C" fn free_custom_service(ptr: *mut CustomService) {
7.68- if ptr.is_null() {
7.69- return;
7.70- }
7.71- let _ = Box::from_raw(ptr);
7.72-}
7.73-#[no_mangle]
7.74-pub unsafe extern "C" fn custom_service_from_string(ptr: *const c_char) -> *mut CustomService {
7.75- assert!(!ptr.is_null());
7.76- let p = CStr::from_ptr(ptr).to_str().unwrap();
7.77- Box::into_raw(Box::new(p.into()))
7.78-}
7.79-#[no_mangle]
7.80-pub unsafe extern "C" fn custom_service_from_json_string(ptr: *const c_char) -> *mut CustomService {
7.81- assert!(!ptr.is_null());
7.82- let s = CStr::from_ptr(ptr);
7.83- Box::into_raw(Box::new(
7.84- CustomService::from_json_str(&s.to_str().unwrap()).unwrap(),
7.85- ))
7.86-}
7.87-#[no_mangle]
7.88-pub unsafe extern "C" fn custom_service_to_json_string(ptr: *const CustomService) -> *mut c_char {
7.89- let p = &*ptr;
7.90- let x = p.to_json_string().unwrap();
7.91- CString::new(x.as_str().as_bytes()).unwrap().into_raw()
7.92-}
7.93-#[no_mangle]
7.94-pub unsafe extern "C" fn custom_service_from_ron_string(ptr: *const c_char) -> *mut CustomService {
7.95- assert!(!ptr.is_null());
7.96- let s = CStr::from_ptr(ptr);
7.97- Box::into_raw(Box::new(
7.98- CustomService::from_ron_str(&s.to_str().unwrap()).unwrap(),
7.99- ))
7.100-}
7.101-#[no_mangle]
7.102-pub unsafe extern "C" fn custom_service_to_ron_string(ptr: *const CustomService) -> *mut c_char {
7.103- let p = &*ptr;
7.104- let x = p.to_ron_string().unwrap();
7.105- CString::new(x.as_str().as_bytes()).unwrap().into_raw()
7.106-}
7.107-#[no_mangle]
7.108-pub unsafe extern "C" fn custom_service_decode(ptr: *const u8, len: size_t) -> *mut CustomService {
7.109- Box::into_raw(Box::new(
7.110- CustomService::decode(slice::from_raw_parts(ptr, len)).unwrap(),
7.111- ))
7.112-}
7.113-#[no_mangle]
7.114-pub unsafe extern "C" fn custom_service_encode(ptr: *const CustomService) -> *mut u8 {
7.115- let p = &*ptr;
7.116- let mut x = p.encode().unwrap();
7.117- let r = x.as_mut_ptr();
7.118- std::mem::forget(x);
7.119- r
7.120-}
8.1--- /dev/null Thu Jan 01 00:00:00 1970 +0000
8.2+++ b/src/package.lisp Tue Jun 06 18:55:17 2023 -0400
8.3@@ -0,0 +1,44 @@
8.4+;; demo packages.lisp
8.5+(defpackage :demo-sys
8.6+ (:nicknames :ds))
8.7+(defpackage :demo-utils
8.8+ (:use :demo-sys)
8.9+ (:nicknames :dutils)
8.10+ (:export
8.11+ #:source-dir
8.12+ #:random-id
8.13+ #:scan-dir)
8.14+ (:export
8.15+ #:*cargo-target*
8.16+ #:*rs-macros*
8.17+ #:rs-defmacro
8.18+ #:rs-macroexpand-1
8.19+ #:rs-macroexpand))
8.20+(defpackage :demo-db
8.21+ (:use :demo-sys)
8.22+ (:nicknames :ddb))
8.23+(defpackage :demo-ui
8.24+ (:use :demo-sys)
8.25+ (:nicknames :dui)
8.26+ (:export
8.27+ #:on-new-window
8.28+ #:start-ui))
8.29+(defpackage :demo-cli
8.30+ (:use :demo-sys)
8.31+ (:nicknames :dcli)
8.32+ (:export
8.33+ #:run-cli
8.34+ #:demo-path
8.35+ #:db-path
8.36+ #:cli-opts
8.37+ #:cli-handler
8.38+ #:cli-cmd))
8.39+(defpackage :demo
8.40+ (:use #:cl #:demo-sys #:demo-utils #:demo-db #:demo-ui #:demo-cli)
8.41+ (:nicknames :d)
8.42+ (:local-nicknames
8.43+ (#:v #:org.shirakumo.verbose)
8.44+ (#:bt #:bordeaux-threads)
8.45+ (#:cli #:clingon)))
8.46+(defpackage :demo-user
8.47+ (:use :demo #:cl-user))
9.1--- a/src/packages.lisp Mon Jun 05 19:59:26 2023 -0400
9.2+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
9.3@@ -1,43 +0,0 @@
9.4-;; demo packages.lisp
9.5-(defpackage :demo-user
9.6- (:use :demo))
9.7-
9.8-(defpackage :demo
9.9- (:use #:cl #:demo-ui #:demo-cli #:demo-tk #:demo-db)
9.10- (:local-nicknames
9.11- (#:v #:org.shirakumo.verbose)
9.12- (#:bt #:bordeaux-threads)
9.13- (#:cli #:clingon)))
9.14-
9.15-(defpackage :demo-ui
9.16- (:use)
9.17- (:export
9.18- #:on-new-window
9.19- #:start-ui))
9.20-(defpackage :demo-tk
9.21- (:use)
9.22- (:export
9.23- #:source-dir
9.24- #:random-id
9.25- #:scan-dir
9.26- #:mkstr
9.27- #:symb
9.28- #:sbq-reader)
9.29- (:export
9.30- #:*cargo-target*
9.31- #:*rs-macros*
9.32- #:rs-defmacro
9.33- #:rs-macroexpand-1
9.34- #:rs-macroexpand))
9.35-(defpackage :demo-cli
9.36- (:use)
9.37- (:local-nick
9.38- (:export
9.39- #:run-cli
9.40- #:demo-path
9.41- #:db-path
9.42- #:cli-opts
9.43- #:cli-handler
9.44- #:cli-cmd))
9.45-(defpackage :demo-db
9.46- (:use))
10.1--- a/src/tk/rs.lisp Mon Jun 05 19:59:26 2023 -0400
10.2+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
10.3@@ -1,78 +0,0 @@
10.4-;;; RUST DSL
10.5-
10.6-;; So basically, this was born out of personal frustration with how
10.7-;; cbindgen and Rust macros work (they don't). Rust macros in general
10.8-;; are something of a pain in my opinion, so I thought why not just
10.9-;; generate Rust code from Lisp instead?
10.10-
10.11-(in-package :demo)
10.12-
10.13-(defvar *cargo-target* #p"/Users/ellis/dev/otom8/demo/target/")
10.14-(defvar *rs-macros* nil)
10.15-
10.16-;; TODO gensyms
10.17-(defmacro rs-defmacro (name args &body body)
10.18- "Define a macro which can be used within the body of a 'with-rs' form."
10.19- `(prog1
10.20- (defmacro ,name ,@(mapcar #`(,a1) args) ,@body)
10.21- (push ',name *rs-macros*)))
10.22-
10.23-(defun rs-mod-form (crate &optional mods pub)
10.24- "Generate a basic mod form (CRATE . [MODS] [PUB])"
10.25- `(,crate ,mods ,pub))
10.26-
10.27-(defmacro with-rs-env (imports &body body)
10.28- "Generate an environment for use within a Rust generator macro."
10.29- `(let ((imports ,(mapcar #'rs-mod-form imports)))
10.30- (format nil "~A~&~A" imports ',body)))
10.31-
10.32-(defun rs-use (crate &optional mods pub)
10.33- "Generate a single Rust use statement."
10.34- (concatenate
10.35- 'string
10.36- (if pub "pub " "")
10.37- "use " crate "::{"
10.38- (cond
10.39- ((consp mods)
10.40- (reduce
10.41- (lambda (x y) (format nil "~A,~A" x y))
10.42- mods))
10.43- (t mods))
10.44- "};"))
10.45-
10.46-(defun rs-mod (mod &optional pub)
10.47- "Generate a single Rust mod statement."
10.48- (concatenate
10.49- 'string
10.50- (if pub "pub " "")
10.51- "mod " mod ";"))
10.52-
10.53-(defun rs-imports (&rest imports)
10.54- "Generate a string of Rust 'use' statements."
10.55- (cond
10.56- ((consp imports)
10.57- (mapcar (lambda (x) (apply #'rs-use (apply #'rs-mod-form x))) imports))
10.58- (t imports)))
10.59-
10.60-(defmacro rs-extern-c-fn (name args &optional pub unsafe no-mangle &body body)
10.61- "Generate a Rust extern 'C' fn."
10.62- `(concatenate
10.63- 'string
10.64- ,(when no-mangle (format nil "#[no_mangle]~&"))
10.65- ,(when pub "pub ")
10.66- ,(when unsafe "unsafe ")
10.67- "extern \"C\" fn " ,name "("
10.68- ,(cond
10.69- ((consp args) (reduce (lambda (x y) (format nil "~A,~A" x y)) args))
10.70- (t args))
10.71- ")" "{" ,@body "}"))
10.72-
10.73-(defun rs-obj-impl (obj)
10.74- "Implement Objective for give OBJ."
10.75- (format nil "impl Objective for ~A {};" obj))
10.76-
10.77-;; (defun rs-macroexpand-1 (form &optional env))
10.78-
10.79-;; (defun rs-macroexpand (env &rest body)
10.80-
10.81-;;;
11.1--- a/src/tk/tk.lisp Mon Jun 05 19:59:26 2023 -0400
11.2+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
11.3@@ -1,28 +0,0 @@
11.4-(in-package :demo)
11.5-
11.6-(defun mkstr (&rest args)
11.7- (with-output-to-string (s)
11.8- (dolist (a args) (princ a s))))
11.9-
11.10-(defun symb (&rest args)
11.11- (values (intern (apply #'mkstr args))))
11.12-
11.13-(defun random-id ()
11.14- (format NIL "~8,'0x-~8,'0x" (random #xFFFFFFFF) (get-universal-time)))
11.15-
11.16-(defun scan-dir (dir filename callback)
11.17- (dolist (path (directory (merge-pathnames (merge-pathnames filename "**/") dir)))
11.18- (funcall callback path)))
11.19-
11.20-(defun sbq-reader (stream sub-char numarg)
11.21- "The anaphoric sharp-backquote reader: #`((,a1))"
11.22- (declare (ignore sub-char))
11.23- (unless numarg (setq numarg 1))
11.24- `(lambda ,(loop for i from 1 to numarg
11.25- collect (symb 'a i))
11.26- ,(funcall
11.27- (get-macro-character #\`) stream nil)))
11.28-
11.29-(eval-when (:load-toplevel)
11.30- (set-dispatch-macro-character
11.31- #\# #\` #'demo:sbq-reader))
12.1--- a/src/ui/ui.lisp Mon Jun 05 19:59:26 2023 -0400
12.2+++ b/src/ui/ui.lisp Tue Jun 06 18:55:17 2023 -0400
12.3@@ -1,4 +1,4 @@
12.4-(in-package :demo)
12.5+(in-package :demo-ui)
12.6
12.7 (defparameter ui-server-port 8080)
12.8 (defparameter ui-server-host "0.0.0.0")
13.1--- /dev/null Thu Jan 01 00:00:00 1970 +0000
13.2+++ b/src/utils/rs.lisp Tue Jun 06 18:55:17 2023 -0400
13.3@@ -0,0 +1,78 @@
13.4+;;; RUST DSL
13.5+
13.6+;; So basically, this was born out of personal frustration with how
13.7+;; cbindgen and Rust macros work (they don't). Rust macros in general
13.8+;; are something of a pain in my opinion, so I thought why not just
13.9+;; generate Rust code from Lisp instead?
13.10+
13.11+(in-package :demo-utils)
13.12+
13.13+(defvar *cargo-target* #p"/Users/ellis/dev/otom8/demo/target/")
13.14+(defvar *rs-macros* nil)
13.15+
13.16+;; TODO gensyms
13.17+(defmacro rs-defmacro (name args &body body)
13.18+ "Define a macro which can be used within the body of a 'with-rs' form."
13.19+ `(prog1
13.20+ (defmacro ,name ,@(mapcar #`(,a1) args) ,@body)
13.21+ (push ',name *rs-macros*)))
13.22+
13.23+(defun rs-mod-form (crate &optional mods pub)
13.24+ "Generate a basic mod form (CRATE . [MODS] [PUB])"
13.25+ `(,crate ,mods ,pub))
13.26+
13.27+(defmacro with-rs-env (imports &body body)
13.28+ "Generate an environment for use within a Rust generator macro."
13.29+ `(let ((imports ,(mapcar #'rs-mod-form imports)))
13.30+ (format nil "~A~&~A" imports ',body)))
13.31+
13.32+(defun rs-use (crate &optional mods pub)
13.33+ "Generate a single Rust use statement."
13.34+ (concatenate
13.35+ 'string
13.36+ (if pub "pub " "")
13.37+ "use " crate "::{"
13.38+ (cond
13.39+ ((consp mods)
13.40+ (reduce
13.41+ (lambda (x y) (format nil "~A,~A" x y))
13.42+ mods))
13.43+ (t mods))
13.44+ "};"))
13.45+
13.46+(defun rs-mod (mod &optional pub)
13.47+ "Generate a single Rust mod statement."
13.48+ (concatenate
13.49+ 'string
13.50+ (if pub "pub " "")
13.51+ "mod " mod ";"))
13.52+
13.53+(defun rs-imports (&rest imports)
13.54+ "Generate a string of Rust 'use' statements."
13.55+ (cond
13.56+ ((consp imports)
13.57+ (mapcar (lambda (x) (apply #'rs-use (apply #'rs-mod-form x))) imports))
13.58+ (t imports)))
13.59+
13.60+(defmacro rs-extern-c-fn (name args &optional pub unsafe no-mangle &body body)
13.61+ "Generate a Rust extern 'C' fn."
13.62+ `(concatenate
13.63+ 'string
13.64+ ,(when no-mangle (format nil "#[no_mangle]~&"))
13.65+ ,(when pub "pub ")
13.66+ ,(when unsafe "unsafe ")
13.67+ "extern \"C\" fn " ,name "("
13.68+ ,(cond
13.69+ ((consp args) (reduce (lambda (x y) (format nil "~A,~A" x y)) args))
13.70+ (t args))
13.71+ ")" "{" ,@body "}"))
13.72+
13.73+(defun rs-obj-impl (obj)
13.74+ "Implement Objective for give OBJ."
13.75+ (format nil "impl Objective for ~A {};" obj))
13.76+
13.77+;; (defun rs-macroexpand-1 (form &optional env))
13.78+
13.79+;; (defun rs-macroexpand (env &rest body)
13.80+
13.81+;;;
14.1--- /dev/null Thu Jan 01 00:00:00 1970 +0000
14.2+++ b/src/utils/utils.lisp Tue Jun 06 18:55:17 2023 -0400
14.3@@ -0,0 +1,28 @@
14.4+(in-package :demo-utils)
14.5+
14.6+(defun mkstr (&rest args)
14.7+ (with-output-to-string (s)
14.8+ (dolist (a args) (princ a s))))
14.9+
14.10+(defun symb (&rest args)
14.11+ (values (intern (apply #'mkstr args))))
14.12+
14.13+(defun random-id ()
14.14+ (format NIL "~8,'0x-~8,'0x" (random #xFFFFFFFF) (get-universal-time)))
14.15+
14.16+(defun scan-dir (dir filename callback)
14.17+ (dolist (path (directory (merge-pathnames (merge-pathnames filename "**/") dir)))
14.18+ (funcall callback path)))
14.19+
14.20+(defun sbq-reader (stream sub-char numarg)
14.21+ "The anaphoric sharp-backquote reader: #`((,a1))"
14.22+ (declare (ignore sub-char))
14.23+ (unless numarg (setq numarg 1))
14.24+ `(lambda ,(loop for i from 1 to numarg
14.25+ collect (symb 'a i))
14.26+ ,(funcall
14.27+ (get-macro-character #\`) stream nil)))
14.28+
14.29+(eval-when (:load-toplevel)
14.30+ (set-dispatch-macro-character
14.31+ #\# #\` #'sbq-reader))
15.1--- /dev/null Thu Jan 01 00:00:00 1970 +0000
15.2+++ b/tools/deps.sh Tue Jun 06 18:55:17 2023 -0400
15.3@@ -0,0 +1,309 @@
15.4+#!/usr/bin/sh
15.5+# install demo build dependencies
15.6+set -u
15.7+PKG_URL_ROOT="${PKG_URL_ROOT:-https://rwest.io/otom8/packy/bundle}"
15.8+PKG_NAME="demo_build_deps"
15.9+say() {printf 'babel-installer: %s\n' "$1"}
15.10+err() {say "$1" >&2; exit 1}
15.11+need_cmd() {
15.12+ if ! check_cmd "$1"; then
15.13+ err "need '$1' (command not found)"
15.14+ fi}
15.15+check_cmd() {command -v "$1" > /dev/null 2>&1}
15.16+ensure() {if ! "$@"; then err "command failed: $*"; fi}
15.17+ignore() {"$@"}
15.18+
15.19+main () {
15.20+ need_cmd chmod
15.21+ need_cmd mkdir
15.22+ need_cmd rm
15.23+
15.24+ get_architecture || return 1
15.25+ local _arch="$RETVAL"
15.26+ assert_nz "$_arch" "arch"
15.27+
15.28+ # no extension unless on windows
15.29+ local _ext=""
15.30+ case "$_arch" in
15.31+ *windows*)
15.32+ _ext=".exe"
15.33+ ;;
15.34+ esac
15.35+
15.36+ local _url="${PKG_URL_ROOT}/bin/dist/${_arch}/${PKG_NAME}${_ext}"
15.37+
15.38+ local _dir
15.39+ _dir="$(ensure mktemp -d)"
15.40+ local _file="${_dir}/${PKG_NAME}${_ext}"
15.41+
15.42+ local _ansi_escapes_are_valid=false
15.43+ if [ -t 2 ]; then
15.44+ if [ "${TERM+set}" = 'set' ]; then
15.45+ case "$TERM" in
15.46+ xterm*|rxvt*|urxvt*|linux*|vt*)
15.47+ _ansi_escapes_are_valid=true
15.48+ ;;
15.49+ esac
15.50+ fi
15.51+ fi
15.52+
15.53+ # check if we have to use /dev/tty to prompt the user
15.54+ local need_tty=yes
15.55+ for arg in "$@"; do
15.56+ case "$arg" in
15.57+ q)
15.58+ # user wants to skip the prompt --
15.59+ # we don't need /dev/tty
15.60+ need_tty=no
15.61+ ;;
15.62+ *)
15.63+ ;;
15.64+ esac
15.65+ done
15.66+
15.67+ if $_ansi_escapes_are_valid; then
15.68+ printf "\33[1minfo:\33[0m downloading $PKG_NAME\n" 1>&2
15.69+ else
15.70+ printf '%s\n' 'info: downloading $PKG_NAME' 1>&2
15.71+ fi
15.72+
15.73+ ensure mkdir -p "$_dir"
15.74+ ensure downloader "$_url" "$_file" "$_arch"
15.75+ ensure chmod u+x "$_file"
15.76+ if [ ! -x "$_file" ]; then
15.77+ printf '%s\n' "Cannot execute $_file (likely because of mounting /tmp as noexec)." 1>&2
15.78+ printf '%s\n' "Please copy the file to a location where you can execute binaries and run ./${PKG_NAME}${_ext}." 1>&2
15.79+ exit 1
15.80+ fi
15.81+
15.82+ if [ "$need_tty" = "yes" ]; then
15.83+ # The installer is going to want to ask for confirmation by
15.84+ # reading stdin. This script was piped into `sh` though and
15.85+ # doesn't have stdin to pass to its children. Instead we're going
15.86+ # to explicitly connect /dev/tty to the installer's stdin.
15.87+ if [ ! -t 1 ]; then
15.88+ err "Unable to run interactively. Run with -y to accept defaults"
15.89+ fi
15.90+
15.91+ ignore "$_file" "$@" < /dev/tty
15.92+ else
15.93+ ignore "$_file" "$@"
15.94+ fi
15.95+
15.96+ local _retval=$?
15.97+
15.98+ ignore rm "$_file"
15.99+ ignore rmdir "$_dir"
15.100+
15.101+ return "$_retval"
15.102+}
15.103+
15.104+dl() { # curl || wget
15.105+ local _dld
15.106+ local _ciphersuites
15.107+ local _err
15.108+ local _status
15.109+ if check_cmd curl; then
15.110+ _dld=curl
15.111+ elif check_cmd wget; then
15.112+ _dld=wget
15.113+ else
15.114+ _dld='curl or wget' # to be used in error message of need_cmd
15.115+ fi
15.116+
15.117+ if [ "$1" = --check ]; then
15.118+ need_cmd "$_dld"
15.119+ elif [ "$_dld" = curl ]; then
15.120+ get_ciphersuites_for_curl
15.121+ _ciphersuites="$RETVAL"
15.122+ if [ -n "$_ciphersuites" ]; then
15.123+ _err=$(curl --proto '=https' --tlsv1.2 --ciphers "$_ciphersuites" --silent --show-error --fail --location "$1" --output "$2" 2>&1)
15.124+ _status=$?
15.125+ else
15.126+ echo "Warning: Not enforcing strong cipher suites for TLS, this is potentially less secure"
15.127+ if ! check_help_for "$3" curl --proto --tlsv1.2; then
15.128+ echo "Warning: Not enforcing TLS v1.2, this is potentially less secure"
15.129+ _err=$(curl --silent --show-error --fail --location "$1" --output "$2" 2>&1)
15.130+ _status=$?
15.131+ else
15.132+ _err=$(curl --proto '=https' --tlsv1.2 --silent --show-error --fail --location "$1" --output "$2" 2>&1)
15.133+ _status=$?
15.134+ fi
15.135+ fi
15.136+ if [ -n "$_err" ]; then
15.137+ echo "$_err" >&2
15.138+ if echo "$_err" | grep -q 404$; then
15.139+ err "installer for platform '$3' not found 8^C - ask ellis to support your platform"
15.140+ fi
15.141+ fi
15.142+ return $_status
15.143+ elif [ "$_dld" = wget ]; then
15.144+ get_ciphersuites_for_wget
15.145+ _ciphersuites="$RETVAL"
15.146+ if [ -n "$_ciphersuites" ]; then
15.147+ _err=$(wget --https-only --secure-protocol=TLSv1_2 --ciphers "$_ciphersuites" "$1" -O "$2" 2>&1)
15.148+ _status=$?
15.149+ else
15.150+ echo "Warning: Not enforcing strong cipher suites for TLS, this is potentially less secure"
15.151+ if ! check_help_for "$3" wget --https-only --secure-protocol; then
15.152+ echo "Warning: Not enforcing TLS v1.2, this is potentially less secure"
15.153+ _err=$(wget "$1" -O "$2" 2>&1)
15.154+ _status=$?
15.155+ else
15.156+ _err=$(wget --https-only --secure-protocol=TLSv1_2 "$1" -O "$2" 2>&1)
15.157+ _status=$?
15.158+ fi
15.159+ fi
15.160+ if [ -n "$_err" ]; then
15.161+ echo "$_err" >&2
15.162+ if echo "$_err" | grep -q ' 404 Not Found$'; then
15.163+ err "installer for platform '$3' not found!"
15.164+ fi
15.165+ fi
15.166+ return $_status
15.167+ else
15.168+ err "Unknown downloader" # should not reach here
15.169+ fi
15.170+}
15.171+
15.172+check_help_for() {
15.173+ local _arch
15.174+ local _cmd
15.175+ local _arg
15.176+ _arch="$1"
15.177+ shift
15.178+ _cmd="$1"
15.179+ shift
15.180+
15.181+ local _category
15.182+ if "$_cmd" --help | grep -q 'For all options use the manual or "--help all".'; then
15.183+ _category="all"
15.184+ else
15.185+ _category=""
15.186+ fi
15.187+
15.188+ case "$_arch" in
15.189+
15.190+ *darwin*)
15.191+ if check_cmd sw_vers; then
15.192+ case $(sw_vers -productVersion) in
15.193+ 10.*)
15.194+ # If we're running on macOS, older than 10.13, then we always
15.195+ # fail to find these options to force fallback
15.196+ if [ "$(sw_vers -productVersion | cut -d. -f2)" -lt 13 ]; then
15.197+ # Older than 10.13
15.198+ echo "Warning: Detected macOS platform older than 10.13"
15.199+ return 1
15.200+ fi
15.201+ ;;
15.202+ 11.*)
15.203+ # We assume Big Sur will be OK for now
15.204+ ;;
15.205+ *)
15.206+ # Unknown product version, warn and continue
15.207+ echo "Warning: Detected unknown macOS major version: $(sw_vers -productVersion)"
15.208+ echo "Warning TLS capabilities detection may fail"
15.209+ ;;
15.210+ esac
15.211+ fi
15.212+ ;;
15.213+
15.214+ esac
15.215+
15.216+ for _arg in "$@"; do
15.217+ if ! "$_cmd" --help $_category | grep -q -- "$_arg"; then
15.218+ return 1
15.219+ fi
15.220+ done
15.221+
15.222+ true # not strictly needed
15.223+}
15.224+
15.225+# Return cipher suite string specified by user, otherwise return strong TLS 1.2-1.3 cipher suites
15.226+# if support by local tools is detected. Detection currently supports these curl backends:
15.227+# GnuTLS and OpenSSL (possibly also LibreSSL and BoringSSL). Return value can be empty.
15.228+get_ciphersuites_for_curl() {
15.229+ if [ -n "${BABEL_TLS_CIPHERSUITES-}" ]; then
15.230+ # user specified custom cipher suites, assume they know what they're doing
15.231+ RETVAL="$BABEL_TLS_CIPHERSUITES"
15.232+ return
15.233+ fi
15.234+
15.235+ local _openssl_syntax="no"
15.236+ local _gnutls_syntax="no"
15.237+ local _backend_supported="yes"
15.238+ if curl -V | grep -q ' OpenSSL/'; then
15.239+ _openssl_syntax="yes"
15.240+ elif curl -V | grep -iq ' LibreSSL/'; then
15.241+ _openssl_syntax="yes"
15.242+ elif curl -V | grep -iq ' BoringSSL/'; then
15.243+ _openssl_syntax="yes"
15.244+ elif curl -V | grep -iq ' GnuTLS/'; then
15.245+ _gnutls_syntax="yes"
15.246+ else
15.247+ _backend_supported="no"
15.248+ fi
15.249+
15.250+ local _args_supported="no"
15.251+ if [ "$_backend_supported" = "yes" ]; then
15.252+ # "unspecified" is for arch, allows for possibility old OS using macports, homebrew, etc.
15.253+ if check_help_for "notspecified" "curl" "--tlsv1.2" "--ciphers" "--proto"; then
15.254+ _args_supported="yes"
15.255+ fi
15.256+ fi
15.257+
15.258+ local _cs=""
15.259+ if [ "$_args_supported" = "yes" ]; then
15.260+ if [ "$_openssl_syntax" = "yes" ]; then
15.261+ _cs=$(get_strong_ciphersuites_for "openssl")
15.262+ elif [ "$_gnutls_syntax" = "yes" ]; then
15.263+ _cs=$(get_strong_ciphersuites_for "gnutls")
15.264+ fi
15.265+ fi
15.266+
15.267+ RETVAL="$_cs"
15.268+}
15.269+
15.270+# Return cipher suite string specified by user, otherwise return strong TLS 1.2-1.3 cipher suites
15.271+# if support by local tools is detected. Detection currently supports these wget backends:
15.272+# GnuTLS and OpenSSL (possibly also LibreSSL and BoringSSL). Return value can be empty.
15.273+get_ciphersuites_for_wget() {
15.274+ if [ -n "${BABEL_TLS_CIPHERSUITES-}" ]; then
15.275+ # user specified custom cipher suites, assume they know what they're doing
15.276+ RETVAL="$BABEL_TLS_CIPHERSUITES"
15.277+ return
15.278+ fi
15.279+
15.280+ local _cs=""
15.281+ if wget -V | grep -q '\-DHAVE_LIBSSL'; then
15.282+ # "unspecified" is for arch, allows for possibility old OS using macports, homebrew, etc.
15.283+ if check_help_for "notspecified" "wget" "TLSv1_2" "--ciphers" "--https-only" "--secure-protocol"; then
15.284+ _cs=$(get_strong_ciphersuites_for "openssl")
15.285+ fi
15.286+ elif wget -V | grep -q '\-DHAVE_LIBGNUTLS'; then
15.287+ # "unspecified" is for arch, allows for possibility old OS using macports, homebrew, etc.
15.288+ if check_help_for "notspecified" "wget" "TLSv1_2" "--ciphers" "--https-only" "--secure-protocol"; then
15.289+ _cs=$(get_strong_ciphersuites_for "gnutls")
15.290+ fi
15.291+ fi
15.292+
15.293+ RETVAL="$_cs"
15.294+}
15.295+
15.296+# Return strong TLS 1.2-1.3 cipher suites in OpenSSL or GnuTLS syntax. TLS 1.2
15.297+# excludes non-ECDHE and non-AEAD cipher suites. DHE is excluded due to bad
15.298+# DH params often found on servers (see RFC 7919). Sequence matches or is
15.299+# similar to Firefox 68 ESR with weak cipher suites disabled via about:config.
15.300+# $1 must be openssl or gnutls.
15.301+get_strong_ciphersuites_for() {
15.302+ if [ "$1" = "openssl" ]; then
15.303+ # OpenSSL is forgiving of unknown values, no problems with TLS 1.3 values on versions that don't support it yet.
15.304+ echo "TLS_AES_128_GCM_SHA256:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_256_GCM_SHA384:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384"
15.305+ elif [ "$1" = "gnutls" ]; then
15.306+ # GnuTLS isn't forgiving of unknown values, so this may require a GnuTLS version that supports TLS 1.3 even if wget doesn't.
15.307+ # Begin with SECURE128 (and higher) then remove/add to build cipher suites. Produces same 9 cipher suites as OpenSSL but in slightly different order.
15.308+ echo "SECURE128:-VERS-SSL3.0:-VERS-TLS1.0:-VERS-TLS1.1:-VERS-DTLS-ALL:-CIPHER-ALL:-MAC-ALL:-KX-ALL:+AEAD:+ECDHE-ECDSA:+ECDHE-RSA:+AES-128-GCM:+CHACHA20-POLY1305:+AES-256-GCM"
15.309+ fi
15.310+}
15.311+
15.312+main "$@" || exit 1