clucumber 0.1.1 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/LICENSE +1 -1
- data/README.md +4 -9
- data/lib/clucumber/clucumber-bootstrap.lisp +32 -0
- data/lib/clucumber/vendor/cl-interpol/alias.lisp +55 -0
- data/lib/clucumber/vendor/cl-interpol/cl-interpol.asd +56 -0
- data/lib/clucumber/vendor/cl-interpol/load.lisp +53 -0
- data/lib/clucumber/vendor/cl-interpol/packages.lisp +40 -0
- data/lib/clucumber/vendor/cl-interpol/read.lisp +716 -0
- data/lib/clucumber/vendor/cl-interpol/specials.lisp +113 -0
- data/lib/clucumber/vendor/cl-interpol/test/packages.lisp +34 -0
- data/lib/clucumber/vendor/cl-interpol/test/tests.lisp +128 -0
- data/lib/clucumber/vendor/cl-interpol/test.lisp +177 -0
- data/lib/clucumber/vendor/cl-interpol/test2.lisp +6254 -0
- data/lib/clucumber/vendor/cl-interpol/unicode.lisp +13912 -0
- data/lib/clucumber/vendor/cl-interpol/util.lisp +122 -0
- data/lib/clucumber/vendor/cl-ppcre/api.lisp +1262 -0
- data/lib/clucumber/vendor/cl-ppcre/charmap.lisp +152 -0
- data/lib/clucumber/vendor/cl-ppcre/charset.lisp +242 -0
- data/lib/clucumber/vendor/cl-ppcre/chartest.lisp +98 -0
- data/lib/clucumber/vendor/cl-ppcre/cl-ppcre-test.asd +34 -0
- data/lib/clucumber/vendor/cl-ppcre/cl-ppcre-unicode/packages.lisp +38 -0
- data/lib/clucumber/vendor/cl-ppcre/cl-ppcre-unicode/resolver.lisp +61 -0
- data/lib/clucumber/vendor/cl-ppcre/cl-ppcre-unicode.asd +58 -0
- data/lib/clucumber/vendor/cl-ppcre/cl-ppcre.asd +79 -0
- data/lib/clucumber/vendor/cl-ppcre/closures.lisp +471 -0
- data/lib/clucumber/vendor/cl-ppcre/convert.lisp +875 -0
- data/lib/clucumber/vendor/cl-ppcre/errors.lisp +84 -0
- data/lib/clucumber/vendor/cl-ppcre/lexer.lisp +737 -0
- data/lib/clucumber/vendor/cl-ppcre/lispworks-defsystem.lisp +57 -0
- data/lib/clucumber/vendor/cl-ppcre/load.lisp +67 -0
- data/lib/clucumber/vendor/cl-ppcre/optimize.lisp +578 -0
- data/lib/clucumber/vendor/cl-ppcre/packages.lisp +68 -0
- data/lib/clucumber/vendor/cl-ppcre/parser.lisp +319 -0
- data/lib/clucumber/vendor/cl-ppcre/ppcre-tests.lisp +269 -0
- data/lib/clucumber/vendor/cl-ppcre/regex-class-util.lisp +555 -0
- data/lib/clucumber/vendor/cl-ppcre/regex-class.lisp +259 -0
- data/lib/clucumber/vendor/cl-ppcre/repetition-closures.lisp +833 -0
- data/lib/clucumber/vendor/cl-ppcre/scanner.lisp +506 -0
- data/lib/clucumber/vendor/cl-ppcre/specials.lisp +172 -0
- data/lib/clucumber/vendor/cl-ppcre/test/packages.lisp +37 -0
- data/lib/clucumber/vendor/cl-ppcre/test/perl-tests.lisp +150 -0
- data/lib/clucumber/vendor/cl-ppcre/test/tests.lisp +159 -0
- data/lib/clucumber/vendor/cl-ppcre/test/unicode-tests.lisp +80 -0
- data/lib/clucumber/vendor/cl-ppcre/util.lisp +201 -0
- data/lib/clucumber/vendor/cl-unicode/alias.lisp +135 -0
- data/lib/clucumber/vendor/cl-unicode/api.lisp +412 -0
- data/lib/clucumber/vendor/cl-unicode/build/char-info.lisp +133 -0
- data/lib/clucumber/vendor/cl-unicode/build/dump.lisp +239 -0
- data/lib/clucumber/vendor/cl-unicode/build/read.lisp +280 -0
- data/lib/clucumber/vendor/cl-unicode/build/util.lisp +182 -0
- data/lib/clucumber/vendor/cl-unicode/cl-unicode.asd +90 -0
- data/lib/clucumber/vendor/cl-unicode/conditions.lisp +54 -0
- data/lib/clucumber/vendor/cl-unicode/derived.lisp +120 -0
- data/lib/clucumber/vendor/cl-unicode/hash-tables.lisp +20 -0
- data/lib/clucumber/vendor/cl-unicode/lists.lisp +10 -0
- data/lib/clucumber/vendor/cl-unicode/methods.lisp +15 -0
- data/lib/clucumber/vendor/cl-unicode/packages.lisp +76 -0
- data/lib/clucumber/vendor/cl-unicode/specials.lisp +135 -0
- data/lib/clucumber/vendor/cl-unicode/test/packages.lisp +34 -0
- data/lib/clucumber/vendor/cl-unicode/test/tests.lisp +150 -0
- data/lib/clucumber/vendor/cl-unicode/test-functions.lisp +94 -0
- data/lib/clucumber/vendor/cl-unicode/util.lisp +274 -0
- data/lib/clucumber/vendor/lift/compare/fiveam-tests.lisp +14 -0
- data/lib/clucumber/vendor/lift/compare/lift-tests.lisp +13 -0
- data/lib/clucumber/vendor/lift/compare/rt-tests.lisp +16 -0
- data/lib/clucumber/vendor/lift/compare/xlunit-tests.lisp +15 -0
- data/lib/clucumber/vendor/lift/dev/changes.lisp +61 -0
- data/lib/clucumber/vendor/lift/dev/config.lisp +354 -0
- data/lib/clucumber/vendor/lift/dev/copy-file.lisp +117 -0
- data/lib/clucumber/vendor/lift/dev/introspection.lisp +232 -0
- data/lib/clucumber/vendor/lift/dev/lift-interface.lisp +56 -0
- data/lib/clucumber/vendor/lift/dev/lift-notes.lisp +202 -0
- data/lib/clucumber/vendor/lift/dev/lift-randomized.lisp +45 -0
- data/lib/clucumber/vendor/lift/dev/lift.lisp +2383 -0
- data/lib/clucumber/vendor/lift/dev/macros.lisp +229 -0
- data/lib/clucumber/vendor/lift/dev/measuring.lisp +156 -0
- data/lib/clucumber/vendor/lift/dev/packages.lisp +161 -0
- data/lib/clucumber/vendor/lift/dev/port.lisp +151 -0
- data/lib/clucumber/vendor/lift/dev/prototypes.lisp +282 -0
- data/lib/clucumber/vendor/lift/dev/random-testing.lisp +124 -0
- data/lib/clucumber/vendor/lift/dev/report-locations.lisp +13 -0
- data/lib/clucumber/vendor/lift/dev/reports.lisp +916 -0
- data/lib/clucumber/vendor/lift/dev/utilities.lisp +242 -0
- data/lib/clucumber/vendor/lift/docs/package.lisp +6 -0
- data/lib/clucumber/vendor/lift/docs/setup.lisp +17 -0
- data/lib/clucumber/vendor/lift/examples/basic-examples.lisp +289 -0
- data/lib/clucumber/vendor/lift/examples/random-testing.lisp +32 -0
- data/lib/clucumber/vendor/lift/lift-documentation.asd +28 -0
- data/lib/clucumber/vendor/lift/lift-test.asd +35 -0
- data/lib/clucumber/vendor/lift/lift.asd +77 -0
- data/lib/clucumber/vendor/lift/test/equality-tests.lisp +40 -0
- data/lib/clucumber/vendor/lift/test/finding-tests.lisp +32 -0
- data/lib/clucumber/vendor/lift/test/lift-test.lisp +783 -0
- data/lib/clucumber/vendor/lift/test/order-of-operations.lisp +54 -0
- data/lib/clucumber/vendor/lift/test/packages.lisp +17 -0
- data/lib/clucumber/vendor/lift/test/test-config-files.lisp +20 -0
- data/lib/clucumber/vendor/lift/test/test-dynamic-variables.lisp +57 -0
- data/lib/clucumber/vendor/lift/test/test-maximum-problems.lisp +74 -0
- data/lib/clucumber/vendor/lift/test/test-prototypes.lisp +278 -0
- data/lib/clucumber/vendor/lift/test/test-timeout.lisp +37 -0
- data/lib/clucumber/vendor/lift/test/tests-in-progress.lisp +62 -0
- data/lib/clucumber/vendor/lift/test/testsuite-expects.lisp +60 -0
- data/lib/clucumber/vendor/lift/timeout/package.lisp +13 -0
- data/lib/clucumber/vendor/lift/timeout/with-timeout.lisp +123 -0
- data/lib/clucumber/vendor/lift/website/stuff/Temp.lisp +34 -0
- data/lib/clucumber/vendor/st-json/st-json.asd +3 -0
- data/lib/clucumber/vendor/st-json/st-json.lisp +310 -0
- data/lib/clucumber/vendor/trivial-backtrace/dev/backtrace.lisp +127 -0
- data/lib/clucumber/vendor/trivial-backtrace/dev/fallback.lisp +10 -0
- data/lib/clucumber/vendor/trivial-backtrace/dev/map-backtrace.lisp +103 -0
- data/lib/clucumber/vendor/trivial-backtrace/dev/mucking.lisp +75 -0
- data/lib/clucumber/vendor/trivial-backtrace/dev/packages.lisp +13 -0
- data/lib/clucumber/vendor/trivial-backtrace/dev/utilities.lisp +104 -0
- data/lib/clucumber/vendor/trivial-backtrace/test/packages.lisp +5 -0
- data/lib/clucumber/vendor/trivial-backtrace/test/test-setup.lisp +4 -0
- data/lib/clucumber/vendor/trivial-backtrace/test/tests.lisp +16 -0
- data/lib/clucumber/vendor/trivial-backtrace/trivial-backtrace-test.asd +22 -0
- data/lib/clucumber/vendor/trivial-backtrace/trivial-backtrace.asd +35 -0
- data/lib/clucumber/vendor/usocket/backend/allegro.lisp +199 -0
- data/lib/clucumber/vendor/usocket/backend/armedbear.lisp +491 -0
- data/lib/clucumber/vendor/usocket/backend/clisp.lisp +260 -0
- data/lib/clucumber/vendor/usocket/backend/cmucl.lisp +266 -0
- data/lib/clucumber/vendor/usocket/backend/lispworks.lisp +741 -0
- data/lib/clucumber/vendor/usocket/backend/mcl.lisp +369 -0
- data/lib/clucumber/vendor/usocket/backend/openmcl.lisp +206 -0
- data/lib/clucumber/vendor/usocket/backend/sbcl.lisp +424 -0
- data/lib/clucumber/vendor/usocket/backend/scl.lisp +261 -0
- data/lib/clucumber/vendor/usocket/condition.lisp +227 -0
- data/lib/clucumber/vendor/usocket/package.lisp +82 -0
- data/lib/clucumber/vendor/usocket/server.lisp +45 -0
- data/lib/clucumber/vendor/usocket/test/package.lisp +13 -0
- data/lib/clucumber/vendor/usocket/test/test-usocket.lisp +166 -0
- data/lib/clucumber/vendor/usocket/usocket-test.asd +26 -0
- data/lib/clucumber/vendor/usocket/usocket.asd +37 -0
- data/lib/clucumber/vendor/usocket/usocket.lisp +542 -0
- data/lib/clucumber/vendor/usocket/vendor/kqueue.lisp +1 -0
- data/lib/clucumber/vendor/usocket/vendor/split-sequence.lisp +245 -0
- data/lib/clucumber.rb +29 -7
- metadata +151 -5
|
@@ -0,0 +1,369 @@
|
|
|
1
|
+
;; MCL backend for USOCKET 0.4.1
|
|
2
|
+
;; Terje Norderhaug <terje@in-progress.com>, January 1, 2009
|
|
3
|
+
|
|
4
|
+
(in-package :ccl)
|
|
5
|
+
|
|
6
|
+
(eval-when (:compile-toplevel :load-toplevel :execute)
|
|
7
|
+
(require :opentransport))
|
|
8
|
+
|
|
9
|
+
;; MCL Issue 28: Passive TCP streams should be able to listen to the loopback interface
|
|
10
|
+
;; see http://code.google.com/p/mcl/issues/detail?id=28 for details
|
|
11
|
+
|
|
12
|
+
(defparameter *passive-interface-address* NIL
|
|
13
|
+
"Address to use for passive connections - optionally bind to loopback address while opening a tcp stream")
|
|
14
|
+
|
|
15
|
+
(advise local-interface-ip-address
|
|
16
|
+
(or *passive-interface-address* (:do-it))
|
|
17
|
+
:when :around :name 'override-local-interface-ip-address)
|
|
18
|
+
|
|
19
|
+
;; MCL Issue 29: Passive TCP connections on OS assigned ports
|
|
20
|
+
;; see http://code.google.com/p/mcl/issues/detail?id=29 for details
|
|
21
|
+
(advise ot-conn-tcp-passive-connect
|
|
22
|
+
(destructuring-bind (conn port &optional (allow-reuse t)) arglist
|
|
23
|
+
(declare (ignore allow-reuse))
|
|
24
|
+
(if (eql port #$kOTAnyInetAddress)
|
|
25
|
+
;; Avoids registering a proxy for port 0 but instead registers one for the true port:
|
|
26
|
+
(multiple-value-bind (proxy result)
|
|
27
|
+
(let* ((*opentransport-class-proxies* NIL) ; makes ot-find-proxy return NIL
|
|
28
|
+
(result (:do-it)) ;; pushes onto *opentransport-class-proxies*
|
|
29
|
+
(proxy (prog1
|
|
30
|
+
(pop *opentransport-class-proxies*)
|
|
31
|
+
(assert (not *opentransport-class-proxies*))))
|
|
32
|
+
(context (cdr proxy))
|
|
33
|
+
(tmpconn (make-ot-conn :context context
|
|
34
|
+
:endpoint (pref context :ot-context.ref)))
|
|
35
|
+
(localaddress (ot-conn-tcp-get-addresses tmpconn)))
|
|
36
|
+
(declare (dynamic-extent tmpconn))
|
|
37
|
+
;; replace original set in body of function
|
|
38
|
+
(setf (ot-conn-local-address conn) localaddress)
|
|
39
|
+
(values
|
|
40
|
+
(cons localaddress context)
|
|
41
|
+
result))
|
|
42
|
+
;; need to be outside local binding of *opentransport-class-proxies*
|
|
43
|
+
(without-interrupts
|
|
44
|
+
(push proxy *opentransport-class-proxies*))
|
|
45
|
+
result)
|
|
46
|
+
(:do-it)))
|
|
47
|
+
:when :around :name 'ot-conn-tcp-passive-connect-any-address)
|
|
48
|
+
|
|
49
|
+
(in-package :usocket)
|
|
50
|
+
|
|
51
|
+
(defun handle-condition (condition &optional socket)
|
|
52
|
+
; incomplete, needs to handle additional conditions
|
|
53
|
+
(flet ((raise-error (&optional socket-condition)
|
|
54
|
+
(if socket-condition
|
|
55
|
+
(error socket-condition :socket socket)
|
|
56
|
+
(error 'unknown-error :socket socket :real-error condition))))
|
|
57
|
+
(typecase condition
|
|
58
|
+
(ccl:host-stopped-responding
|
|
59
|
+
(raise-error 'host-down-error))
|
|
60
|
+
(ccl:host-not-responding
|
|
61
|
+
(raise-error 'host-unreachable-error))
|
|
62
|
+
(ccl:connection-reset
|
|
63
|
+
(raise-error 'connection-reset-error))
|
|
64
|
+
(ccl:connection-timed-out
|
|
65
|
+
(raise-error 'timeout-error))
|
|
66
|
+
(ccl:opentransport-protocol-error
|
|
67
|
+
(raise-error 'protocol-not-supported-error))
|
|
68
|
+
(otherwise
|
|
69
|
+
(raise-error)))))
|
|
70
|
+
|
|
71
|
+
(defun socket-connect (host port &key (element-type 'character) timeout deadline nodelay
|
|
72
|
+
local-host local-port)
|
|
73
|
+
(with-mapped-conditions ()
|
|
74
|
+
(let* ((socket
|
|
75
|
+
(make-instance 'active-socket
|
|
76
|
+
:remote-host (when host (host-to-hostname host))
|
|
77
|
+
:remote-port port
|
|
78
|
+
:local-host (when local-host (host-to-hostname local-host))
|
|
79
|
+
:local-port local-port
|
|
80
|
+
:deadline deadline
|
|
81
|
+
:nodelay nodelay
|
|
82
|
+
:connect-timeout (and timeout (round (* timeout 60)))
|
|
83
|
+
:element-type element-type))
|
|
84
|
+
(stream (socket-open-stream socket)))
|
|
85
|
+
(make-stream-socket :socket socket :stream stream))))
|
|
86
|
+
|
|
87
|
+
(defun socket-listen (host port
|
|
88
|
+
&key reuseaddress
|
|
89
|
+
(reuse-address nil reuse-address-supplied-p)
|
|
90
|
+
(backlog 5)
|
|
91
|
+
(element-type 'character))
|
|
92
|
+
(declare (ignore reuseaddress reuse-address-supplied-p))
|
|
93
|
+
(let ((socket (with-mapped-conditions ()
|
|
94
|
+
(make-instance 'passive-socket
|
|
95
|
+
:local-port port
|
|
96
|
+
:local-host host
|
|
97
|
+
:reuse-address reuse-address
|
|
98
|
+
:backlog backlog))))
|
|
99
|
+
(make-stream-server-socket socket :element-type element-type)))
|
|
100
|
+
|
|
101
|
+
(defmethod socket-accept ((usocket stream-server-usocket) &key element-type)
|
|
102
|
+
(let* ((socket (socket usocket))
|
|
103
|
+
(stream (with-mapped-conditions (usocket)
|
|
104
|
+
(socket-accept socket :element-type element-type))))
|
|
105
|
+
(make-stream-socket :socket socket :stream stream)))
|
|
106
|
+
|
|
107
|
+
(defmethod socket-close ((usocket usocket))
|
|
108
|
+
(with-mapped-conditions (usocket)
|
|
109
|
+
(socket-close (socket usocket))))
|
|
110
|
+
|
|
111
|
+
(defmethod ccl::stream-close ((usocket usocket))
|
|
112
|
+
(socket-close usocket))
|
|
113
|
+
|
|
114
|
+
(defun get-hosts-by-name (name)
|
|
115
|
+
(with-mapped-conditions ()
|
|
116
|
+
(list (hbo-to-vector-quad (ccl::get-host-address
|
|
117
|
+
(host-to-hostname name))))))
|
|
118
|
+
|
|
119
|
+
(defun get-host-by-address (address)
|
|
120
|
+
(with-mapped-conditions ()
|
|
121
|
+
(ccl::inet-host-name (host-to-hbo address))))
|
|
122
|
+
|
|
123
|
+
(defmethod get-local-name ((usocket usocket))
|
|
124
|
+
(values (get-local-address usocket)
|
|
125
|
+
(get-local-port usocket)))
|
|
126
|
+
|
|
127
|
+
(defmethod get-peer-name ((usocket stream-usocket))
|
|
128
|
+
(values (get-peer-address usocket)
|
|
129
|
+
(get-peer-port usocket)))
|
|
130
|
+
|
|
131
|
+
(defmethod get-local-address ((usocket usocket))
|
|
132
|
+
(hbo-to-vector-quad (ccl::get-host-address (or (local-host (socket usocket)) ""))))
|
|
133
|
+
|
|
134
|
+
(defmethod get-local-port ((usocket usocket))
|
|
135
|
+
(local-port (socket usocket)))
|
|
136
|
+
|
|
137
|
+
(defmethod get-peer-address ((usocket stream-usocket))
|
|
138
|
+
(hbo-to-vector-quad (ccl::get-host-address (remote-host (socket usocket)))))
|
|
139
|
+
|
|
140
|
+
(defmethod get-peer-port ((usocket stream-usocket))
|
|
141
|
+
(remote-port (socket usocket)))
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
(defun %setup-wait-list (wait-list)
|
|
145
|
+
(declare (ignore wait-list)))
|
|
146
|
+
|
|
147
|
+
(defun %add-waiter (wait-list waiter)
|
|
148
|
+
(declare (ignore wait-list waiter)))
|
|
149
|
+
|
|
150
|
+
(defun %remove-waiter (wait-list waiter)
|
|
151
|
+
(declare (ignore wait-list waiter)))
|
|
152
|
+
|
|
153
|
+
|
|
154
|
+
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
155
|
+
;; BASIC MCL SOCKET IMPLEMENTATION
|
|
156
|
+
|
|
157
|
+
(defclass socket ()
|
|
158
|
+
((local-port :reader local-port :initarg :local-port)
|
|
159
|
+
(local-host :reader local-host :initarg :local-host)
|
|
160
|
+
(element-type :reader element-type :initform 'ccl::base-character :initarg :element-type)))
|
|
161
|
+
|
|
162
|
+
(defclass active-socket (socket)
|
|
163
|
+
((remote-host :reader remote-host :initarg :remote-host)
|
|
164
|
+
(remote-port :reader remote-port :initarg :remote-port)
|
|
165
|
+
(deadline :initarg :deadline)
|
|
166
|
+
(nodelay :initarg :nodelay)
|
|
167
|
+
(connect-timeout :reader connect-timeout :initform NIL :initarg :connect-timeout
|
|
168
|
+
:type (or null fixnum) :documentation "ticks (60th of a second)")))
|
|
169
|
+
|
|
170
|
+
(defmethod socket-open-stream ((socket active-socket))
|
|
171
|
+
(ccl::open-tcp-stream (or (remote-host socket)(ccl::local-interface-ip-address)) (remote-port socket)
|
|
172
|
+
:element-type (if (subtypep (element-type socket) 'character) 'ccl::base-character 'unsigned-byte)
|
|
173
|
+
:connect-timeout (connect-timeout socket)))
|
|
174
|
+
|
|
175
|
+
(defmethod socket-close ((socket active-socket))
|
|
176
|
+
NIL)
|
|
177
|
+
|
|
178
|
+
(defclass passive-socket (socket)
|
|
179
|
+
((streams :accessor socket-streams :type list :initform NIL
|
|
180
|
+
:documentation "Circular list of streams with first element the next to open")
|
|
181
|
+
(reuse-address :reader reuse-address :initarg :reuse-address)
|
|
182
|
+
(lock :reader socket-lock :initform (ccl:make-lock "Socket"))))
|
|
183
|
+
|
|
184
|
+
(defmethod initialize-instance :after ((socket passive-socket) &key backlog)
|
|
185
|
+
(loop repeat backlog
|
|
186
|
+
collect (socket-open-listener socket) into streams
|
|
187
|
+
finally (setf (socket-streams socket)
|
|
188
|
+
(cdr (rplacd (last streams) streams))))
|
|
189
|
+
(when (zerop (local-port socket))
|
|
190
|
+
(setf (slot-value socket 'local-port)
|
|
191
|
+
(or (ccl::process-wait-with-timeout "binding port" (* 10 60)
|
|
192
|
+
#'ccl::stream-local-port (car (socket-streams socket)))
|
|
193
|
+
(error "timeout")))))
|
|
194
|
+
|
|
195
|
+
(defmethod socket-accept ((socket passive-socket) &key element-type &aux (lock (socket-lock socket)))
|
|
196
|
+
(flet ((connection-established-p (stream)
|
|
197
|
+
(ccl::with-io-buffer-locked ((ccl::stream-io-buffer stream nil))
|
|
198
|
+
(let ((state (ccl::opentransport-stream-connection-state stream)))
|
|
199
|
+
(not (eq :unbnd state))))))
|
|
200
|
+
(with-mapped-conditions ()
|
|
201
|
+
(ccl:with-lock-grabbed (lock nil "Socket Lock")
|
|
202
|
+
(let ((connection (shiftf (car (socket-streams socket))
|
|
203
|
+
(socket-open-listener socket element-type))))
|
|
204
|
+
(pop (socket-streams socket))
|
|
205
|
+
(ccl:process-wait "Accepting" #'connection-established-p connection)
|
|
206
|
+
connection)))))
|
|
207
|
+
|
|
208
|
+
(defmethod socket-close ((socket passive-socket))
|
|
209
|
+
(loop
|
|
210
|
+
with streams = (socket-streams socket)
|
|
211
|
+
for (stream tail) on streams
|
|
212
|
+
do (close stream :abort T)
|
|
213
|
+
until (eq tail streams)
|
|
214
|
+
finally (setf (socket-streams socket) NIL)))
|
|
215
|
+
|
|
216
|
+
(defmethod socket-open-listener (socket &optional element-type)
|
|
217
|
+
; see http://code.google.com/p/mcl/issues/detail?id=28
|
|
218
|
+
(let* ((ccl::*passive-interface-address* (local-host socket))
|
|
219
|
+
(new (ccl::open-tcp-stream NIL (or (local-port socket) #$kOTAnyInetAddress)
|
|
220
|
+
:reuse-local-port-p (reuse-address socket)
|
|
221
|
+
:element-type (if (subtypep (or element-type (element-type socket))
|
|
222
|
+
'character)
|
|
223
|
+
'ccl::base-character
|
|
224
|
+
'unsigned-byte))))
|
|
225
|
+
(declare (special ccl::*passive-interface-address*))
|
|
226
|
+
new))
|
|
227
|
+
|
|
228
|
+
|
|
229
|
+
(defun wait-for-input-internal (wait-list &key timeout &aux result)
|
|
230
|
+
(macrolet ((when-io-buffer-lock-grabbed ((lock &optional multiple-value-p) &body body)
|
|
231
|
+
"Evaluates the body if and only if the lock is successfully grabbed"
|
|
232
|
+
;; like with-io-buffer-lock-grabbed but returns immediately instead of polling the lock
|
|
233
|
+
(let ((needs-unlocking-p (gensym))
|
|
234
|
+
(lock-var (gensym)))
|
|
235
|
+
`(let* ((,lock-var ,lock)
|
|
236
|
+
(ccl::*grabbed-io-buffer-locks* (cons ,lock-var ccl::*grabbed-io-buffer-locks*))
|
|
237
|
+
(,needs-unlocking-p (needs-unlocking-p ,lock-var)))
|
|
238
|
+
(declare (dynamic-extent ccl::*grabbed-io-buffer-locks*))
|
|
239
|
+
(when ,needs-unlocking-p
|
|
240
|
+
(,(if multiple-value-p 'multiple-value-prog1 'prog1)
|
|
241
|
+
(progn ,@body)
|
|
242
|
+
(ccl::%release-io-buffer-lock ,lock-var)))))))
|
|
243
|
+
(labels ((needs-unlocking-p (lock)
|
|
244
|
+
(declare (type ccl::lock lock))
|
|
245
|
+
;; crucial - clears bogus lock.value as in grab-io-buffer-lock-out-of-line:
|
|
246
|
+
(ccl::%io-buffer-lock-really-grabbed-p lock)
|
|
247
|
+
(ccl:store-conditional lock nil ccl:*current-process*))
|
|
248
|
+
(input-available (stream)
|
|
249
|
+
"similar to stream-listen on buffered-input-stream-mixin but without waiting for lock"
|
|
250
|
+
(let ((io-buffer (ccl::stream-io-buffer stream)))
|
|
251
|
+
(or (not (eql 0 (ccl::io-buffer-incount io-buffer)))
|
|
252
|
+
(ccl::io-buffer-untyi-char io-buffer)
|
|
253
|
+
(locally (declare (optimize (speed 3) (safety 0)))
|
|
254
|
+
(when-io-buffer-lock-grabbed ((ccl::io-buffer-lock io-buffer))
|
|
255
|
+
(funcall (ccl::io-buffer-listen-function io-buffer) stream io-buffer))))))
|
|
256
|
+
(ready-sockets (sockets)
|
|
257
|
+
(dolist (sock sockets result)
|
|
258
|
+
(when (input-available (socket-stream sock))
|
|
259
|
+
(push sock result)))))
|
|
260
|
+
(with-mapped-conditions ()
|
|
261
|
+
(ccl:process-wait-with-timeout
|
|
262
|
+
"socket input"
|
|
263
|
+
(when timeout (truncate (* timeout 60)))
|
|
264
|
+
#'ready-sockets
|
|
265
|
+
(wait-list-waiters wait-list)))
|
|
266
|
+
(nreverse result))))
|
|
267
|
+
|
|
268
|
+
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
269
|
+
#| Test for wait-for-input
|
|
270
|
+
(let* ((sock1 (usocket:socket-connect "in-progress.com" 80))
|
|
271
|
+
(sock2 (usocket:socket-connect "common-lisp.net" 80))
|
|
272
|
+
(sockets (list sock1 sock2)))
|
|
273
|
+
(dolist (sock sockets)
|
|
274
|
+
(format (usocket:socket-stream sock)
|
|
275
|
+
"GET / HTTP/1.0~A~A~A~A"
|
|
276
|
+
#\Return #\Linefeed #\Return #\Linefeed)
|
|
277
|
+
(force-output (usocket:socket-stream sock)))
|
|
278
|
+
(wait-for-input sockets :timeout 5000))
|
|
279
|
+
|#
|
|
280
|
+
|
|
281
|
+
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
282
|
+
#| TEST (from test-usocket.lisp)
|
|
283
|
+
|
|
284
|
+
|
|
285
|
+
(defparameter +non-existing-host+ "192.168.1.1")
|
|
286
|
+
(defparameter +unused-local-port+ 15213)
|
|
287
|
+
(defparameter *soc1* (usocket::make-stream-socket :socket :my-socket
|
|
288
|
+
:stream :my-stream))
|
|
289
|
+
(defparameter +common-lisp-net+ #(208 72 159 207)) ;; common-lisp.net IP
|
|
290
|
+
|
|
291
|
+
|
|
292
|
+
(usocket:socket *soc1*)
|
|
293
|
+
|
|
294
|
+
(usocket:socket-connect "127.0.0.0" +unused-local-port+)
|
|
295
|
+
|
|
296
|
+
(usocket:socket-connect #(127 0 0 0) +unused-local-port+)
|
|
297
|
+
|
|
298
|
+
(usocket:socket-connect 2130706432 +unused-local-port+)
|
|
299
|
+
|
|
300
|
+
(let ((sock (usocket:socket-connect "common-lisp.net" 80)))
|
|
301
|
+
(unwind-protect
|
|
302
|
+
(typep sock 'usocket:usocket)
|
|
303
|
+
(usocket:socket-close sock)))
|
|
304
|
+
|
|
305
|
+
(let ((sock (usocket:socket-connect +common-lisp-net+ 80)))
|
|
306
|
+
(unwind-protect
|
|
307
|
+
(typep sock 'usocket:usocket)
|
|
308
|
+
(usocket:socket-close sock)))
|
|
309
|
+
|
|
310
|
+
(let ((sock (usocket:socket-connect (usocket::host-byte-order +common-lisp-net+) 80)))
|
|
311
|
+
(unwind-protect
|
|
312
|
+
(typep sock 'usocket:usocket)
|
|
313
|
+
(usocket:socket-close sock)))
|
|
314
|
+
|
|
315
|
+
(let ((sock (usocket:socket-connect "common-lisp.net" 80)))
|
|
316
|
+
(unwind-protect
|
|
317
|
+
(progn
|
|
318
|
+
(format (usocket:socket-stream sock)
|
|
319
|
+
"GET / HTTP/1.0~A~A~A~A"
|
|
320
|
+
#\Return #\Linefeed #\Return #\Linefeed)
|
|
321
|
+
(force-output (usocket:socket-stream sock))
|
|
322
|
+
(read-line (usocket:socket-stream sock)))
|
|
323
|
+
(usocket:socket-close sock)))
|
|
324
|
+
|
|
325
|
+
(let ((sock (usocket:socket-connect +common-lisp-net+ 80)))
|
|
326
|
+
(unwind-protect
|
|
327
|
+
(usocket::get-peer-address sock)
|
|
328
|
+
(usocket:socket-close sock)))
|
|
329
|
+
|
|
330
|
+
(let ((sock (usocket:socket-connect +common-lisp-net+ 80)))
|
|
331
|
+
(unwind-protect
|
|
332
|
+
(usocket::get-peer-port sock)
|
|
333
|
+
(usocket:socket-close sock)))
|
|
334
|
+
|
|
335
|
+
(let ((sock (usocket:socket-connect +common-lisp-net+ 80)))
|
|
336
|
+
(unwind-protect
|
|
337
|
+
(usocket::get-peer-name sock)
|
|
338
|
+
(usocket:socket-close sock)))
|
|
339
|
+
|
|
340
|
+
(let ((sock (usocket:socket-connect +common-lisp-net+ 80)))
|
|
341
|
+
(unwind-protect
|
|
342
|
+
(usocket::get-local-address sock)
|
|
343
|
+
(usocket:socket-close sock)))
|
|
344
|
+
|
|
345
|
+
|#
|
|
346
|
+
|
|
347
|
+
|
|
348
|
+
#|
|
|
349
|
+
|
|
350
|
+
(defun socket-server (host port)
|
|
351
|
+
(let ((socket (socket-listen host port)))
|
|
352
|
+
(unwind-protect
|
|
353
|
+
(loop
|
|
354
|
+
(with-open-stream (stream (socket-stream (socket-accept socket)))
|
|
355
|
+
(ccl::telnet-write-line stream "~A"
|
|
356
|
+
(reverse (ccl::telnet-read-line stream)))
|
|
357
|
+
(ccl::force-output stream)))
|
|
358
|
+
(close socket))))
|
|
359
|
+
|
|
360
|
+
(ccl::process-run-function "Socket Server" #'socket-server NIL 4088)
|
|
361
|
+
|
|
362
|
+
(let* ((sock (socket-connect nil 4088))
|
|
363
|
+
(stream (usocket:socket-stream sock)))
|
|
364
|
+
(assert (streamp stream))
|
|
365
|
+
(ccl::telnet-write-line stream "hello ~A" (random 10))
|
|
366
|
+
(ccl::force-output stream)
|
|
367
|
+
(ccl::telnet-read-line stream))
|
|
368
|
+
|
|
369
|
+
|#
|
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
;;;; $Id: openmcl.lisp 522 2010-05-02 01:57:55Z ctian $
|
|
2
|
+
;;;; $URL: svn://common-lisp.net/project/usocket/svn/usocket/trunk/backend/openmcl.lisp $
|
|
3
|
+
|
|
4
|
+
;;;; See LICENSE for licensing information.
|
|
5
|
+
|
|
6
|
+
(in-package :usocket)
|
|
7
|
+
|
|
8
|
+
(defun get-host-name ()
|
|
9
|
+
(ccl::%stack-block ((resultbuf 256))
|
|
10
|
+
(when (zerop (#_gethostname resultbuf 256))
|
|
11
|
+
(ccl::%get-cstring resultbuf))))
|
|
12
|
+
|
|
13
|
+
(defparameter +openmcl-error-map+
|
|
14
|
+
'((:address-in-use . address-in-use-error)
|
|
15
|
+
(:connection-aborted . connection-aborted-error)
|
|
16
|
+
(:no-buffer-space . no-buffers-error)
|
|
17
|
+
(:connection-timed-out . timeout-error)
|
|
18
|
+
(:connection-refused . connection-refused-error)
|
|
19
|
+
(:host-unreachable . host-unreachable-error)
|
|
20
|
+
(:host-down . host-down-error)
|
|
21
|
+
(:network-down . network-down-error)
|
|
22
|
+
(:address-not-available . address-not-available-error)
|
|
23
|
+
(:network-reset . network-reset-error)
|
|
24
|
+
(:connection-reset . connection-reset-error)
|
|
25
|
+
(:shutdown . shutdown-error)
|
|
26
|
+
(:access-denied . operation-not-permitted-error)))
|
|
27
|
+
|
|
28
|
+
(defparameter +openmcl-nameserver-error-map+
|
|
29
|
+
'((:no-recovery . ns-no-recovery-error)
|
|
30
|
+
(:try-again . ns-try-again-condition)
|
|
31
|
+
(:host-not-found . ns-host-not-found-error)))
|
|
32
|
+
|
|
33
|
+
;; we need something which the openmcl implementors 'forgot' to do:
|
|
34
|
+
;; wait for more than one socket-or-fd
|
|
35
|
+
|
|
36
|
+
(defun input-available-p (sockets &optional ticks-to-wait)
|
|
37
|
+
(ccl::rletZ ((tv :timeval))
|
|
38
|
+
(ccl::ticks-to-timeval ticks-to-wait tv)
|
|
39
|
+
;;### The trickery below can be moved to the wait-list now...
|
|
40
|
+
(ccl::%stack-block ((infds ccl::*fd-set-size*))
|
|
41
|
+
(ccl::fd-zero infds)
|
|
42
|
+
(let ((max-fd -1))
|
|
43
|
+
(dolist (sock sockets)
|
|
44
|
+
(let ((fd (openmcl-socket:socket-os-fd (socket sock))))
|
|
45
|
+
(setf max-fd (max max-fd fd))
|
|
46
|
+
(ccl::fd-set fd infds)))
|
|
47
|
+
(let* ((res (#_select (1+ max-fd)
|
|
48
|
+
infds (ccl::%null-ptr) (ccl::%null-ptr)
|
|
49
|
+
(if ticks-to-wait tv (ccl::%null-ptr)))))
|
|
50
|
+
(when (> res 0)
|
|
51
|
+
(dolist (x sockets)
|
|
52
|
+
(when (ccl::fd-is-set (openmcl-socket:socket-os-fd (socket x))
|
|
53
|
+
infds)
|
|
54
|
+
(setf (state x) :READ))))
|
|
55
|
+
sockets)))))
|
|
56
|
+
|
|
57
|
+
(defun raise-error-from-id (condition-id socket real-condition)
|
|
58
|
+
(let ((usock-err (cdr (assoc condition-id +openmcl-error-map+))))
|
|
59
|
+
(if usock-err
|
|
60
|
+
(error usock-err :socket socket)
|
|
61
|
+
(error 'unknown-error :socket socket :real-error real-condition))))
|
|
62
|
+
|
|
63
|
+
(defun handle-condition (condition &optional socket)
|
|
64
|
+
(typecase condition
|
|
65
|
+
(openmcl-socket:socket-error
|
|
66
|
+
(raise-error-from-id (openmcl-socket:socket-error-identifier condition)
|
|
67
|
+
socket condition))
|
|
68
|
+
(ccl:input-timeout
|
|
69
|
+
(error 'timeout-error :socket socket))
|
|
70
|
+
(ccl:communication-deadline-expired
|
|
71
|
+
(error 'deadline-timeout-error :socket socket))
|
|
72
|
+
(ccl::socket-creation-error #| ugh! |#
|
|
73
|
+
(let* ((condition-id (ccl::socket-creation-error-identifier condition))
|
|
74
|
+
(nameserver-error (cdr (assoc condition-id
|
|
75
|
+
+openmcl-nameserver-error-map+))))
|
|
76
|
+
(if nameserver-error
|
|
77
|
+
(error nameserver-error :host-or-ip nil)
|
|
78
|
+
(raise-error-from-id condition-id socket condition))))))
|
|
79
|
+
|
|
80
|
+
(defun to-format (element-type)
|
|
81
|
+
(if (subtypep element-type 'character)
|
|
82
|
+
:text
|
|
83
|
+
:binary))
|
|
84
|
+
|
|
85
|
+
(defun socket-connect (host port &key (protocol :stream) (element-type 'character)
|
|
86
|
+
timeout deadline nodelay
|
|
87
|
+
local-host local-port)
|
|
88
|
+
(with-mapped-conditions ()
|
|
89
|
+
(ecase protocol
|
|
90
|
+
(:stream
|
|
91
|
+
(let ((mcl-sock
|
|
92
|
+
(openmcl-socket:make-socket :remote-host (host-to-hostname host)
|
|
93
|
+
:remote-port port
|
|
94
|
+
:local-host (when local-host (host-to-hostname local-host))
|
|
95
|
+
:local-port local-port
|
|
96
|
+
:format (to-format element-type)
|
|
97
|
+
:deadline deadline
|
|
98
|
+
:nodelay nodelay
|
|
99
|
+
:connect-timeout timeout)))
|
|
100
|
+
(openmcl-socket:socket-connect mcl-sock)
|
|
101
|
+
(make-stream-socket :stream mcl-sock :socket mcl-sock)))
|
|
102
|
+
(:datagram
|
|
103
|
+
(let ((mcl-sock
|
|
104
|
+
(openmcl-socket:make-socket :address-family :internet
|
|
105
|
+
:type :datagram
|
|
106
|
+
:local-host (when local-host (host-to-hostname local-host))
|
|
107
|
+
:local-port local-port
|
|
108
|
+
:format :binary)))
|
|
109
|
+
(when (and host port)
|
|
110
|
+
(ccl::inet-connect (ccl::socket-device mcl-sock)
|
|
111
|
+
(ccl::host-as-inet-host host)
|
|
112
|
+
(ccl::port-as-inet-port port "udp")))
|
|
113
|
+
(make-datagram-socket mcl-sock))))))
|
|
114
|
+
|
|
115
|
+
(defun socket-listen (host port
|
|
116
|
+
&key reuseaddress
|
|
117
|
+
(reuse-address nil reuse-address-supplied-p)
|
|
118
|
+
(backlog 5)
|
|
119
|
+
(element-type 'character))
|
|
120
|
+
(let* ((reuseaddress (if reuse-address-supplied-p reuse-address reuseaddress))
|
|
121
|
+
(sock (with-mapped-conditions ()
|
|
122
|
+
(apply #'openmcl-socket:make-socket
|
|
123
|
+
(append (list :connect :passive
|
|
124
|
+
:reuse-address reuseaddress
|
|
125
|
+
:local-port port
|
|
126
|
+
:backlog backlog
|
|
127
|
+
:format (to-format element-type))
|
|
128
|
+
(when (ip/= host *wildcard-host*)
|
|
129
|
+
(list :local-host host)))))))
|
|
130
|
+
(make-stream-server-socket sock :element-type element-type)))
|
|
131
|
+
|
|
132
|
+
(defmethod socket-accept ((usocket stream-server-usocket) &key element-type)
|
|
133
|
+
(declare (ignore element-type)) ;; openmcl streams are bi/multivalent
|
|
134
|
+
(let ((sock (with-mapped-conditions (usocket)
|
|
135
|
+
(openmcl-socket:accept-connection (socket usocket)))))
|
|
136
|
+
(make-stream-socket :socket sock :stream sock)))
|
|
137
|
+
|
|
138
|
+
;; One close method is sufficient because sockets
|
|
139
|
+
;; and their associated objects are represented
|
|
140
|
+
;; by the same object.
|
|
141
|
+
(defmethod socket-close ((usocket usocket))
|
|
142
|
+
(when (wait-list usocket)
|
|
143
|
+
(remove-waiter (wait-list usocket) usocket))
|
|
144
|
+
(with-mapped-conditions (usocket)
|
|
145
|
+
(close (socket usocket))))
|
|
146
|
+
|
|
147
|
+
(defmethod socket-send ((usocket datagram-usocket) buffer length &key host port)
|
|
148
|
+
(with-mapped-conditions (usocket)
|
|
149
|
+
(openmcl-socket:send-to (socket usocket) buffer length
|
|
150
|
+
:remote-host (if host (host-to-hbo host))
|
|
151
|
+
:remote-port port)))
|
|
152
|
+
|
|
153
|
+
(defmethod socket-receive ((usocket datagram-usocket) buffer length &key)
|
|
154
|
+
(with-mapped-conditions (usocket)
|
|
155
|
+
(openmcl-socket:receive-from (socket usocket) length :buffer buffer)))
|
|
156
|
+
|
|
157
|
+
(defmethod get-local-address ((usocket usocket))
|
|
158
|
+
(let ((address (openmcl-socket:local-host (socket usocket))))
|
|
159
|
+
(when address
|
|
160
|
+
(hbo-to-vector-quad address))))
|
|
161
|
+
|
|
162
|
+
(defmethod get-peer-address ((usocket stream-usocket))
|
|
163
|
+
(let ((address (openmcl-socket:remote-host (socket usocket))))
|
|
164
|
+
(when address
|
|
165
|
+
(hbo-to-vector-quad address))))
|
|
166
|
+
|
|
167
|
+
(defmethod get-local-port ((usocket usocket))
|
|
168
|
+
(openmcl-socket:local-port (socket usocket)))
|
|
169
|
+
|
|
170
|
+
(defmethod get-peer-port ((usocket stream-usocket))
|
|
171
|
+
(openmcl-socket:remote-port (socket usocket)))
|
|
172
|
+
|
|
173
|
+
(defmethod get-local-name ((usocket usocket))
|
|
174
|
+
(values (get-local-address usocket)
|
|
175
|
+
(get-local-port usocket)))
|
|
176
|
+
|
|
177
|
+
(defmethod get-peer-name ((usocket stream-usocket))
|
|
178
|
+
(values (get-peer-address usocket)
|
|
179
|
+
(get-peer-port usocket)))
|
|
180
|
+
|
|
181
|
+
(defun get-host-by-address (address)
|
|
182
|
+
(with-mapped-conditions ()
|
|
183
|
+
(openmcl-socket:ipaddr-to-hostname (host-to-hbo address))))
|
|
184
|
+
|
|
185
|
+
(defun get-hosts-by-name (name)
|
|
186
|
+
(with-mapped-conditions ()
|
|
187
|
+
(list (hbo-to-vector-quad (openmcl-socket:lookup-hostname
|
|
188
|
+
(host-to-hostname name))))))
|
|
189
|
+
|
|
190
|
+
|
|
191
|
+
(defun %setup-wait-list (wait-list)
|
|
192
|
+
(declare (ignore wait-list)))
|
|
193
|
+
|
|
194
|
+
(defun %add-waiter (wait-list waiter)
|
|
195
|
+
(declare (ignore wait-list waiter)))
|
|
196
|
+
|
|
197
|
+
(defun %remove-waiter (wait-list waiter)
|
|
198
|
+
(declare (ignore wait-list waiter)))
|
|
199
|
+
|
|
200
|
+
(defun wait-for-input-internal (wait-list &key timeout)
|
|
201
|
+
(with-mapped-conditions ()
|
|
202
|
+
(let* ((ticks-timeout (truncate (* (or timeout 1)
|
|
203
|
+
ccl::*ticks-per-second*))))
|
|
204
|
+
(input-available-p (wait-list-waiters wait-list)
|
|
205
|
+
(when timeout ticks-timeout))
|
|
206
|
+
wait-list)))
|