| 1 |
;;; Copyright (C) 2005 David Lichteblau |
|---|
| 2 |
;;; |
|---|
| 3 |
;;; See LICENSE for details. |
|---|
| 4 |
|
|---|
| 5 |
(in-package cl+ssl) |
|---|
| 6 |
|
|---|
| 7 |
(defconstant +bio-type-socket+ (logior 5 #x0400 #x0100)) |
|---|
| 8 |
(defconstant +BIO_FLAGS_READ+ 1) |
|---|
| 9 |
(defconstant +BIO_FLAGS_WRITE+ 2) |
|---|
| 10 |
(defconstant +BIO_FLAGS_SHOULD_RETRY+ 8) |
|---|
| 11 |
(defconstant +BIO_CTRL_FLUSH+ 11) |
|---|
| 12 |
|
|---|
| 13 |
(cffi:defcstruct bio-method |
|---|
| 14 |
(type :int) |
|---|
| 15 |
(name :pointer) |
|---|
| 16 |
(bwrite :pointer) |
|---|
| 17 |
(bread :pointer) |
|---|
| 18 |
(bputs :pointer) |
|---|
| 19 |
(bgets :pointer) |
|---|
| 20 |
(ctrl :pointer) |
|---|
| 21 |
(create :pointer) |
|---|
| 22 |
(destroy :pointer) |
|---|
| 23 |
(callback-ctrl :pointer)) |
|---|
| 24 |
|
|---|
| 25 |
(cffi:defcstruct bio |
|---|
| 26 |
(method :pointer) |
|---|
| 27 |
(callback :pointer) |
|---|
| 28 |
(cb-arg :pointer) |
|---|
| 29 |
(init :int) |
|---|
| 30 |
(shutdown :int) |
|---|
| 31 |
(flags :int) |
|---|
| 32 |
(retry-reason :int) |
|---|
| 33 |
(num :int) |
|---|
| 34 |
(ptr :pointer) |
|---|
| 35 |
(next-bio :pointer) |
|---|
| 36 |
(prev-bio :pointer) |
|---|
| 37 |
(references :int) |
|---|
| 38 |
(num-read :unsigned-long) |
|---|
| 39 |
(num-write :unsigned-long) |
|---|
| 40 |
(crypto-ex-data-stack :pointer) |
|---|
| 41 |
(crypto-ex-data-dummy :int)) |
|---|
| 42 |
|
|---|
| 43 |
(defun make-bio-lisp-method () |
|---|
| 44 |
(let ((m (cffi:foreign-alloc 'bio-method))) |
|---|
| 45 |
(setf (cffi:foreign-slot-value m 'bio-method 'type) |
|---|
| 46 |
;; fixme: this is wrong, but presumably still better than some |
|---|
| 47 |
;; random value here. |
|---|
| 48 |
+bio-type-socket+) |
|---|
| 49 |
(macrolet ((slot (name) |
|---|
| 50 |
`(cffi:foreign-slot-value m 'bio-method ,name))) |
|---|
| 51 |
(setf (slot 'name) (cffi:foreign-string-alloc "lisp")) |
|---|
| 52 |
(setf (slot 'bwrite) (cffi:callback lisp-write)) |
|---|
| 53 |
(setf (slot 'bread) (cffi:callback lisp-read)) |
|---|
| 54 |
(setf (slot 'bputs) (cffi:callback lisp-puts)) |
|---|
| 55 |
(setf (slot 'bgets) (cffi:null-pointer)) |
|---|
| 56 |
(setf (slot 'ctrl) (cffi:callback lisp-ctrl)) |
|---|
| 57 |
(setf (slot 'create) (cffi:callback lisp-create)) |
|---|
| 58 |
(setf (slot 'destroy) (cffi:callback lisp-destroy)) |
|---|
| 59 |
(setf (slot 'callback-ctrl) (cffi:null-pointer))) |
|---|
| 60 |
m)) |
|---|
| 61 |
|
|---|
| 62 |
(defun bio-new-lisp () |
|---|
| 63 |
(bio-new *bio-lisp-method*)) |
|---|
| 64 |
|
|---|
| 65 |
|
|---|
| 66 |
;;; "cargo cult" |
|---|
| 67 |
|
|---|
| 68 |
(cffi:defcallback lisp-write :int ((bio :pointer) (buf :pointer) (n :int)) |
|---|
| 69 |
bio |
|---|
| 70 |
(dotimes (i n) |
|---|
| 71 |
(write-byte (cffi:mem-ref buf :unsigned-char i) *socket*)) |
|---|
| 72 |
(finish-output *socket*) |
|---|
| 73 |
n) |
|---|
| 74 |
|
|---|
| 75 |
(defun clear-retry-flags (bio) |
|---|
| 76 |
(setf (cffi:foreign-slot-value bio 'bio 'flags) |
|---|
| 77 |
(logandc2 (cffi:foreign-slot-value bio 'bio 'flags) |
|---|
| 78 |
(logior +BIO_FLAGS_READ+ |
|---|
| 79 |
+BIO_FLAGS_WRITE+ |
|---|
| 80 |
+BIO_FLAGS_SHOULD_RETRY+)))) |
|---|
| 81 |
|
|---|
| 82 |
(defun set-retry-read (bio) |
|---|
| 83 |
(setf (cffi:foreign-slot-value bio 'bio 'flags) |
|---|
| 84 |
(logior (cffi:foreign-slot-value bio 'bio 'flags) |
|---|
| 85 |
+BIO_FLAGS_READ+ |
|---|
| 86 |
+BIO_FLAGS_SHOULD_RETRY+))) |
|---|
| 87 |
|
|---|
| 88 |
(cffi:defcallback lisp-read :int ((bio :pointer) (buf :pointer) (n :int)) |
|---|
| 89 |
bio buf n |
|---|
| 90 |
(let ((i 0)) |
|---|
| 91 |
(handler-case |
|---|
| 92 |
(unless (or (cffi:null-pointer-p buf) (null n)) |
|---|
| 93 |
(clear-retry-flags bio) |
|---|
| 94 |
(when (or *blockp* (listen *socket*)) |
|---|
| 95 |
(setf (cffi:mem-ref buf :unsigned-char i) (read-byte *socket*)) |
|---|
| 96 |
(incf i)) |
|---|
| 97 |
(loop |
|---|
| 98 |
while (and (< i n) |
|---|
| 99 |
(or (null *partial-read-p*) (listen *socket*))) |
|---|
| 100 |
do |
|---|
| 101 |
(setf (cffi:mem-ref buf :unsigned-char i) (read-byte *socket*)) |
|---|
| 102 |
(incf i)) |
|---|
| 103 |
#+(or) |
|---|
| 104 |
(when (zerop i) (set-retry-read bio))) |
|---|
| 105 |
(end-of-file ())) |
|---|
| 106 |
i)) |
|---|
| 107 |
|
|---|
| 108 |
(cffi:defcallback lisp-puts :int ((bio :pointer) (buf :string)) |
|---|
| 109 |
bio buf |
|---|
| 110 |
(error "lisp-puts not implemented")) |
|---|
| 111 |
|
|---|
| 112 |
(cffi:defcallback lisp-ctrl :int |
|---|
| 113 |
((bio :pointer) (cmd :int) (larg :long) (parg :pointer)) |
|---|
| 114 |
bio larg parg |
|---|
| 115 |
(cond |
|---|
| 116 |
((eql cmd +BIO_CTRL_FLUSH+) 1) |
|---|
| 117 |
(t |
|---|
| 118 |
;; (warn "lisp-ctrl(~A,~A,~A)" cmd larg parg) |
|---|
| 119 |
0))) |
|---|
| 120 |
|
|---|
| 121 |
(cffi:defcallback lisp-create :int ((bio :pointer)) |
|---|
| 122 |
(setf (cffi:foreign-slot-value bio 'bio 'init) 1) |
|---|
| 123 |
(setf (cffi:foreign-slot-value bio 'bio 'num) 0) |
|---|
| 124 |
(setf (cffi:foreign-slot-value bio 'bio 'ptr) (cffi:null-pointer)) |
|---|
| 125 |
(setf (cffi:foreign-slot-value bio 'bio 'flags) 0) |
|---|
| 126 |
1) |
|---|
| 127 |
|
|---|
| 128 |
(cffi:defcallback lisp-destroy :int ((bio :pointer)) |
|---|
| 129 |
(cond |
|---|
| 130 |
((cffi:null-pointer-p bio) 0) |
|---|
| 131 |
(t |
|---|
| 132 |
(setf (cffi:foreign-slot-value bio 'bio 'init) 0) |
|---|
| 133 |
(setf (cffi:foreign-slot-value bio 'bio 'flags) 0) |
|---|
| 134 |
1))) |
|---|
| 135 |
|
|---|
| 136 |
(setf *bio-lisp-method* nil) ;force reinit if anything changed here |
|---|