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,260 @@
|
|
|
1
|
+
;;;; $Id: clisp.lisp 515 2010-01-07 18:26:06Z ctian $
|
|
2
|
+
;;;; $URL: svn://common-lisp.net/project/usocket/svn/usocket/trunk/backend/clisp.lisp $
|
|
3
|
+
|
|
4
|
+
;;;; See LICENSE for licensing information.
|
|
5
|
+
|
|
6
|
+
(in-package :usocket)
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
;; utility routine for looking up the current host name
|
|
10
|
+
(FFI:DEF-CALL-OUT get-host-name-internal
|
|
11
|
+
(:name "gethostname")
|
|
12
|
+
(:arguments (name (FFI:C-PTR (FFI:C-ARRAY-MAX ffi:character 256))
|
|
13
|
+
:OUT :ALLOCA)
|
|
14
|
+
(len ffi:int))
|
|
15
|
+
#+win32 (:library "WS2_32")
|
|
16
|
+
(:language #-win32 :stdc
|
|
17
|
+
#+win32 :stdc-stdcall)
|
|
18
|
+
(:return-type ffi:int))
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
(defun get-host-name ()
|
|
22
|
+
(multiple-value-bind (retcode name)
|
|
23
|
+
(get-host-name-internal 256)
|
|
24
|
+
(when (= retcode 0)
|
|
25
|
+
name)))
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
#+win32
|
|
29
|
+
(defun remap-maybe-for-win32 (z)
|
|
30
|
+
(mapcar #'(lambda (x)
|
|
31
|
+
(cons (mapcar #'(lambda (y)
|
|
32
|
+
(+ 10000 y))
|
|
33
|
+
(car x))
|
|
34
|
+
(cdr x)))
|
|
35
|
+
z))
|
|
36
|
+
|
|
37
|
+
(defparameter +clisp-error-map+
|
|
38
|
+
#+win32
|
|
39
|
+
(append (remap-maybe-for-win32 +unix-errno-condition-map+)
|
|
40
|
+
(remap-maybe-for-win32 +unix-errno-error-map+))
|
|
41
|
+
#-win32
|
|
42
|
+
(append +unix-errno-condition-map+
|
|
43
|
+
+unix-errno-error-map+))
|
|
44
|
+
|
|
45
|
+
(defun handle-condition (condition &optional (socket nil))
|
|
46
|
+
"Dispatch correct usocket condition."
|
|
47
|
+
(typecase condition
|
|
48
|
+
(system::simple-os-error
|
|
49
|
+
(let ((usock-err
|
|
50
|
+
(cdr (assoc (car (simple-condition-format-arguments condition))
|
|
51
|
+
+clisp-error-map+ :test #'member))))
|
|
52
|
+
(when usock-err ;; don't claim the error if we don't know
|
|
53
|
+
;; it's actually a socket error ...
|
|
54
|
+
(if (subtypep usock-err 'error)
|
|
55
|
+
(error usock-err :socket socket)
|
|
56
|
+
(signal usock-err :socket socket)))))))
|
|
57
|
+
|
|
58
|
+
(defun socket-connect (host port &key (protocol :stream) (element-type 'character)
|
|
59
|
+
timeout deadline (nodelay t nodelay-specified)
|
|
60
|
+
local-host local-port)
|
|
61
|
+
(declare (ignore nodelay))
|
|
62
|
+
(when timeout (unsupported 'timeout 'socket-connect))
|
|
63
|
+
(when deadline (unsupported 'deadline 'socket-connect))
|
|
64
|
+
(when nodelay-specified (unsupported 'nodelay 'socket-connect))
|
|
65
|
+
(when local-host (unsupported 'local-host 'socket-connect))
|
|
66
|
+
(when local-port (unsupported 'local-port 'socket-connect))
|
|
67
|
+
|
|
68
|
+
(let ((socket)
|
|
69
|
+
(hostname (host-to-hostname host)))
|
|
70
|
+
(with-mapped-conditions (socket)
|
|
71
|
+
(setf socket
|
|
72
|
+
(if timeout
|
|
73
|
+
(socket:socket-connect port hostname
|
|
74
|
+
:element-type element-type
|
|
75
|
+
:buffered t
|
|
76
|
+
:timeout timeout)
|
|
77
|
+
(socket:socket-connect port hostname
|
|
78
|
+
:element-type element-type
|
|
79
|
+
:buffered t))))
|
|
80
|
+
(make-stream-socket :socket socket
|
|
81
|
+
:stream socket))) ;; the socket is a stream too
|
|
82
|
+
|
|
83
|
+
(defun socket-listen (host port
|
|
84
|
+
&key reuseaddress
|
|
85
|
+
(reuse-address nil reuse-address-supplied-p)
|
|
86
|
+
(backlog 5)
|
|
87
|
+
(element-type 'character))
|
|
88
|
+
;; clisp 2.39 sets SO_REUSEADDRESS to 1 by default; no need to
|
|
89
|
+
;; to explicitly turn it on; unfortunately, there's no way to turn it off...
|
|
90
|
+
(declare (ignore reuseaddress reuse-address reuse-address-supplied-p))
|
|
91
|
+
(let ((sock (apply #'socket:socket-server
|
|
92
|
+
(append (list port
|
|
93
|
+
:backlog backlog)
|
|
94
|
+
(when (ip/= host *wildcard-host*)
|
|
95
|
+
(list :interface host))))))
|
|
96
|
+
(with-mapped-conditions ()
|
|
97
|
+
(make-stream-server-socket sock :element-type element-type))))
|
|
98
|
+
|
|
99
|
+
(defmethod socket-accept ((socket stream-server-usocket) &key element-type)
|
|
100
|
+
(let ((stream
|
|
101
|
+
(with-mapped-conditions (socket)
|
|
102
|
+
(socket:socket-accept (socket socket)
|
|
103
|
+
:element-type (or element-type
|
|
104
|
+
(element-type socket))))))
|
|
105
|
+
(make-stream-socket :socket stream
|
|
106
|
+
:stream stream)))
|
|
107
|
+
|
|
108
|
+
;; Only one close method required:
|
|
109
|
+
;; sockets and their associated streams
|
|
110
|
+
;; are the same object
|
|
111
|
+
(defmethod socket-close ((usocket usocket))
|
|
112
|
+
"Close socket."
|
|
113
|
+
(when (wait-list usocket)
|
|
114
|
+
(remove-waiter (wait-list usocket) usocket))
|
|
115
|
+
(with-mapped-conditions (usocket)
|
|
116
|
+
(close (socket usocket))))
|
|
117
|
+
|
|
118
|
+
(defmethod socket-close ((usocket stream-server-usocket))
|
|
119
|
+
(when (wait-list usocket)
|
|
120
|
+
(remove-waiter (wait-list usocket) usocket))
|
|
121
|
+
(socket:socket-server-close (socket usocket)))
|
|
122
|
+
|
|
123
|
+
(defmethod get-local-name ((usocket usocket))
|
|
124
|
+
(multiple-value-bind
|
|
125
|
+
(address port)
|
|
126
|
+
(socket:socket-stream-local (socket usocket) t)
|
|
127
|
+
(values (dotted-quad-to-vector-quad address) port)))
|
|
128
|
+
|
|
129
|
+
(defmethod get-peer-name ((usocket stream-usocket))
|
|
130
|
+
(multiple-value-bind
|
|
131
|
+
(address port)
|
|
132
|
+
(socket:socket-stream-peer (socket usocket) t)
|
|
133
|
+
(values (dotted-quad-to-vector-quad address) port)))
|
|
134
|
+
|
|
135
|
+
(defmethod get-local-address ((usocket usocket))
|
|
136
|
+
(nth-value 0 (get-local-name usocket)))
|
|
137
|
+
|
|
138
|
+
(defmethod get-peer-address ((usocket stream-usocket))
|
|
139
|
+
(nth-value 0 (get-peer-name usocket)))
|
|
140
|
+
|
|
141
|
+
(defmethod get-local-port ((usocket usocket))
|
|
142
|
+
(nth-value 1 (get-local-name usocket)))
|
|
143
|
+
|
|
144
|
+
(defmethod get-peer-port ((usocket stream-usocket))
|
|
145
|
+
(nth-value 1 (get-peer-name usocket)))
|
|
146
|
+
|
|
147
|
+
|
|
148
|
+
(defun %setup-wait-list (wait-list)
|
|
149
|
+
(declare (ignore wait-list)))
|
|
150
|
+
|
|
151
|
+
(defun %add-waiter (wait-list waiter)
|
|
152
|
+
(push (cons (socket waiter) NIL) (wait-list-%wait wait-list)))
|
|
153
|
+
|
|
154
|
+
(defun %remove-waiter (wait-list waiter)
|
|
155
|
+
(setf (wait-list-%wait wait-list)
|
|
156
|
+
(remove (socket waiter) (wait-list-%wait wait-list) :key #'car)))
|
|
157
|
+
|
|
158
|
+
(defmethod wait-for-input-internal (wait-list &key timeout)
|
|
159
|
+
(with-mapped-conditions ()
|
|
160
|
+
(multiple-value-bind
|
|
161
|
+
(secs musecs)
|
|
162
|
+
(split-timeout (or timeout 1))
|
|
163
|
+
(dolist (x (wait-list-%wait wait-list))
|
|
164
|
+
(setf (cdr x) :INPUT))
|
|
165
|
+
(let* ((request-list (wait-list-%wait wait-list))
|
|
166
|
+
(status-list (if timeout
|
|
167
|
+
(socket:socket-status request-list secs musecs)
|
|
168
|
+
(socket:socket-status request-list)))
|
|
169
|
+
(sockets (wait-list-waiters wait-list)))
|
|
170
|
+
(do* ((x (pop sockets) (pop sockets))
|
|
171
|
+
(y (pop status-list) (pop status-list)))
|
|
172
|
+
((null x))
|
|
173
|
+
(when (eq y :INPUT)
|
|
174
|
+
(setf (state x) :READ)))
|
|
175
|
+
wait-list))))
|
|
176
|
+
|
|
177
|
+
|
|
178
|
+
;;
|
|
179
|
+
;; UDP/Datagram sockets!
|
|
180
|
+
;;
|
|
181
|
+
|
|
182
|
+
#+rawsock
|
|
183
|
+
(progn
|
|
184
|
+
|
|
185
|
+
(defun make-sockaddr_in ()
|
|
186
|
+
(make-array 16 :element-type '(unsigned-byte 8) :initial-element 0))
|
|
187
|
+
|
|
188
|
+
(declaim (inline fill-sockaddr_in))
|
|
189
|
+
(defun fill-sockaddr_in (sockaddr_in ip port)
|
|
190
|
+
(port-to-octet-buffer sockaddr_in port)
|
|
191
|
+
(ip-to-octet-buffer sockaddr_in ip :start 2)
|
|
192
|
+
sockaddr_in)
|
|
193
|
+
|
|
194
|
+
(defun socket-create-datagram (local-port
|
|
195
|
+
&key (local-host *wildcard-host*)
|
|
196
|
+
remote-host
|
|
197
|
+
remote-port)
|
|
198
|
+
(let ((sock (rawsock:socket :inet :dgram 0))
|
|
199
|
+
(lsock_addr (fill-sockaddr_in (make-sockaddr_in)
|
|
200
|
+
local-host local-port))
|
|
201
|
+
(rsock_addr (when remote-host
|
|
202
|
+
(fill-sockaddr_in (make-sockaddr_in)
|
|
203
|
+
remote-host (or remote-port
|
|
204
|
+
local-port)))))
|
|
205
|
+
(bind sock lsock_addr)
|
|
206
|
+
(when rsock_addr
|
|
207
|
+
(connect sock rsock_addr))
|
|
208
|
+
(make-datagram-socket sock :connected-p (if rsock_addr t nil))))
|
|
209
|
+
|
|
210
|
+
(defun socket-receive (socket buffer &key (size (length buffer)))
|
|
211
|
+
"Returns the buffer, the number of octets copied into the buffer (received)
|
|
212
|
+
and the address of the sender as values."
|
|
213
|
+
(let* ((sock (socket socket))
|
|
214
|
+
(sockaddr (when (not (connected-p socket))
|
|
215
|
+
(rawsock:make-sockaddr)))
|
|
216
|
+
(rv (if sockaddr
|
|
217
|
+
(rawsock:recvfrom sock buffer sockaddr
|
|
218
|
+
:start 0
|
|
219
|
+
:end size)
|
|
220
|
+
(rawsock:recv sock buffer
|
|
221
|
+
:start 0
|
|
222
|
+
:end size))))
|
|
223
|
+
(values buffer
|
|
224
|
+
rv
|
|
225
|
+
(list (ip-from-octet-buffer (sockaddr-data sockaddr) 4)
|
|
226
|
+
(port-from-octet-buffer (sockaddr-data sockaddr) 2)))))
|
|
227
|
+
|
|
228
|
+
(defun socket-send (socket buffer &key address (size (length buffer)))
|
|
229
|
+
"Returns the number of octets sent."
|
|
230
|
+
(let* ((sock (socket socket))
|
|
231
|
+
(sockaddr (when address
|
|
232
|
+
(rawsock:make-sockaddr :INET
|
|
233
|
+
(fill-sockaddr_in
|
|
234
|
+
(make-sockaddr_in)
|
|
235
|
+
(host-byte-order
|
|
236
|
+
(second address))
|
|
237
|
+
(first address)))))
|
|
238
|
+
(rv (if address
|
|
239
|
+
(rawsock:sendto sock buffer sockaddr
|
|
240
|
+
:start 0
|
|
241
|
+
:end size)
|
|
242
|
+
(rawsock:send sock buffer
|
|
243
|
+
:start 0
|
|
244
|
+
:end size))))
|
|
245
|
+
rv))
|
|
246
|
+
|
|
247
|
+
(defmethod socket-close ((usocket datagram-usocket))
|
|
248
|
+
(when (wait-list usocket)
|
|
249
|
+
(remove-waiter (wait-list usocket) usocket))
|
|
250
|
+
(rawsock:sock-close (socket usocket)))
|
|
251
|
+
|
|
252
|
+
)
|
|
253
|
+
|
|
254
|
+
#-rawsock
|
|
255
|
+
(progn
|
|
256
|
+
(warn "This image doesn't contain the RAWSOCK package.
|
|
257
|
+
To enable UDP socket support, please be sure to use the -Kfull parameter
|
|
258
|
+
at startup, or to enable RAWSOCK support during compilation.")
|
|
259
|
+
|
|
260
|
+
)
|
|
@@ -0,0 +1,266 @@
|
|
|
1
|
+
;;;; $Id: cmucl.lisp 515 2010-01-07 18:26:06Z ctian $
|
|
2
|
+
;;;; $URL: svn://common-lisp.net/project/usocket/svn/usocket/trunk/backend/cmucl.lisp $
|
|
3
|
+
|
|
4
|
+
;;;; See LICENSE for licensing information.
|
|
5
|
+
|
|
6
|
+
(in-package :usocket)
|
|
7
|
+
|
|
8
|
+
#+win32
|
|
9
|
+
(defun remap-for-win32 (z)
|
|
10
|
+
(mapcar #'(lambda (x)
|
|
11
|
+
(cons (mapcar #'(lambda (y)
|
|
12
|
+
(+ 10000 y))
|
|
13
|
+
(car x))
|
|
14
|
+
(cdr x)))
|
|
15
|
+
z))
|
|
16
|
+
|
|
17
|
+
(defparameter +cmucl-error-map+
|
|
18
|
+
#+win32
|
|
19
|
+
(append (remap-for-win32 +unix-errno-condition-map+)
|
|
20
|
+
(remap-for-win32 +unix-errno-error-map+))
|
|
21
|
+
#-win32
|
|
22
|
+
(append +unix-errno-condition-map+
|
|
23
|
+
+unix-errno-error-map+))
|
|
24
|
+
|
|
25
|
+
(defun cmucl-map-socket-error (err &key condition socket)
|
|
26
|
+
(let ((usock-err
|
|
27
|
+
(cdr (assoc err +cmucl-error-map+ :test #'member))))
|
|
28
|
+
(if usock-err
|
|
29
|
+
(if (subtypep usock-err 'error)
|
|
30
|
+
(error usock-err :socket socket)
|
|
31
|
+
(signal usock-err :socket socket))
|
|
32
|
+
(error 'unknown-error
|
|
33
|
+
:socket socket
|
|
34
|
+
:real-error condition))))
|
|
35
|
+
|
|
36
|
+
;; CMUCL error handling is brain-dead: it doesn't preserve any
|
|
37
|
+
;; information other than the OS error string from which the
|
|
38
|
+
;; error can be determined. The OS error string isn't good enough
|
|
39
|
+
;; given that it may have been localized (l10n).
|
|
40
|
+
;;
|
|
41
|
+
;; The above applies to versions pre 19b; 19d and newer are expected to
|
|
42
|
+
;; contain even better error reporting.
|
|
43
|
+
;;
|
|
44
|
+
;;
|
|
45
|
+
;; Just catch the errors and encapsulate them in an unknown-error
|
|
46
|
+
(defun handle-condition (condition &optional (socket nil))
|
|
47
|
+
"Dispatch correct usocket condition."
|
|
48
|
+
(typecase condition
|
|
49
|
+
(ext::socket-error (cmucl-map-socket-error (ext::socket-errno condition)
|
|
50
|
+
:socket socket
|
|
51
|
+
:condition condition))))
|
|
52
|
+
|
|
53
|
+
(defun socket-connect (host port &key (protocol :stream) (element-type 'character)
|
|
54
|
+
timeout deadline (nodelay t nodelay-specified)
|
|
55
|
+
(local-host nil local-host-p)
|
|
56
|
+
(local-port nil local-port-p)
|
|
57
|
+
&aux
|
|
58
|
+
(local-bind-p (fboundp 'ext::bind-inet-socket)))
|
|
59
|
+
(declare (ignore nodelay))
|
|
60
|
+
(when timeout (unsupported 'timeout 'socket-connect))
|
|
61
|
+
(when deadline (unsupported 'deadline 'socket-connect))
|
|
62
|
+
(when nodelay-specified (unsupported 'nodelay 'socket-connect))
|
|
63
|
+
(when (and local-host-p (not local-bind-p))
|
|
64
|
+
(unsupported 'local-host 'socket-connect :minimum "Snapshot 2008-08 (19E)"))
|
|
65
|
+
(when (and local-port-p (not local-bind-p))
|
|
66
|
+
(unsupported 'local-port 'socket-connect :minimum "Snapshot 2008-08 (19E)"))
|
|
67
|
+
|
|
68
|
+
(let ((socket))
|
|
69
|
+
(ecase protocol
|
|
70
|
+
(:stream
|
|
71
|
+
(setf socket
|
|
72
|
+
(let ((args (list (host-to-hbo host) port protocol)))
|
|
73
|
+
(when (and local-bind-p (or local-host-p local-port-p))
|
|
74
|
+
(nconc args (list :local-host (when local-host
|
|
75
|
+
(host-to-hbo local-host))
|
|
76
|
+
:local-port local-port)))
|
|
77
|
+
(with-mapped-conditions (socket)
|
|
78
|
+
(apply #'ext:connect-to-inet-socket args))))
|
|
79
|
+
(if socket
|
|
80
|
+
(let* ((stream (sys:make-fd-stream socket :input t :output t
|
|
81
|
+
:element-type element-type
|
|
82
|
+
:buffering :full))
|
|
83
|
+
;;###FIXME the above line probably needs an :external-format
|
|
84
|
+
(usocket (make-stream-socket :socket socket
|
|
85
|
+
:stream stream)))
|
|
86
|
+
usocket)
|
|
87
|
+
(let ((err (unix:unix-errno)))
|
|
88
|
+
(when err (cmucl-map-socket-error err)))))
|
|
89
|
+
(:datagram
|
|
90
|
+
(setf socket
|
|
91
|
+
(if (and host port)
|
|
92
|
+
(let ((args (list (host-to-hbo host) port protocol)))
|
|
93
|
+
(when (and local-bind-p (or local-host-p local-port-p))
|
|
94
|
+
(nconc args (list :local-host (when local-host
|
|
95
|
+
(host-to-hbo local-host))
|
|
96
|
+
:local-port local-port)))
|
|
97
|
+
(with-mapped-conditions (socket)
|
|
98
|
+
(apply #'ext:connect-to-inet-socket args)))
|
|
99
|
+
(if (or local-host-p local-port-p)
|
|
100
|
+
(with-mapped-conditions (socket)
|
|
101
|
+
(apply #'ext:create-inet-listener
|
|
102
|
+
(nconc (list (or local-port 0) protocol)
|
|
103
|
+
(when (and local-host-p
|
|
104
|
+
(ip/= local-host *wildcard-host*))
|
|
105
|
+
(list :host (host-to-hbo local-host))))))
|
|
106
|
+
(with-mapped-conditions (socket)
|
|
107
|
+
(ext:create-inet-socket protocol)))))
|
|
108
|
+
(if socket
|
|
109
|
+
(let ((usocket (make-datagram-socket socket)))
|
|
110
|
+
(ext:finalize usocket #'(lambda () (when (%open-p usocket)
|
|
111
|
+
(ext:close-socket socket))))
|
|
112
|
+
usocket)
|
|
113
|
+
(let ((err (unix:unix-errno)))
|
|
114
|
+
(when err (cmucl-map-socket-error err))))))))
|
|
115
|
+
|
|
116
|
+
(defun socket-listen (host port
|
|
117
|
+
&key reuseaddress
|
|
118
|
+
(reuse-address nil reuse-address-supplied-p)
|
|
119
|
+
(backlog 5)
|
|
120
|
+
(element-type 'character))
|
|
121
|
+
(let* ((reuseaddress (if reuse-address-supplied-p reuse-address reuseaddress))
|
|
122
|
+
(server-sock
|
|
123
|
+
(with-mapped-conditions ()
|
|
124
|
+
(apply #'ext:create-inet-listener
|
|
125
|
+
(nconc (list port :stream
|
|
126
|
+
:backlog backlog
|
|
127
|
+
:reuse-address reuseaddress)
|
|
128
|
+
(when (ip/= host *wildcard-host*)
|
|
129
|
+
(list :host
|
|
130
|
+
(host-to-hbo host))))))))
|
|
131
|
+
(make-stream-server-socket server-sock :element-type element-type)))
|
|
132
|
+
|
|
133
|
+
(defmethod socket-accept ((usocket stream-server-usocket) &key element-type)
|
|
134
|
+
(with-mapped-conditions (usocket)
|
|
135
|
+
(let* ((sock (ext:accept-tcp-connection (socket usocket)))
|
|
136
|
+
(stream (sys:make-fd-stream sock :input t :output t
|
|
137
|
+
:element-type (or element-type
|
|
138
|
+
(element-type usocket))
|
|
139
|
+
:buffering :full)))
|
|
140
|
+
(make-stream-socket :socket sock :stream stream))))
|
|
141
|
+
|
|
142
|
+
;; Sockets and socket streams are represented
|
|
143
|
+
;; by different objects. Be sure to close the
|
|
144
|
+
;; socket stream when closing a stream socket.
|
|
145
|
+
(defmethod socket-close ((usocket stream-usocket))
|
|
146
|
+
"Close socket."
|
|
147
|
+
(when (wait-list usocket)
|
|
148
|
+
(remove-waiter (wait-list usocket) usocket))
|
|
149
|
+
(with-mapped-conditions (usocket)
|
|
150
|
+
(close (socket-stream usocket))))
|
|
151
|
+
|
|
152
|
+
(defmethod socket-close ((usocket usocket))
|
|
153
|
+
"Close socket."
|
|
154
|
+
(when (wait-list usocket)
|
|
155
|
+
(remove-waiter (wait-list usocket) usocket))
|
|
156
|
+
(with-mapped-conditions (usocket)
|
|
157
|
+
(ext:close-socket (socket usocket))))
|
|
158
|
+
|
|
159
|
+
(defmethod socket-close :after ((socket datagram-usocket))
|
|
160
|
+
(setf (%open-p socket) nil))
|
|
161
|
+
|
|
162
|
+
(defmethod socket-send ((usocket datagram-usocket) buffer length &key host port)
|
|
163
|
+
(with-mapped-conditions (usocket)
|
|
164
|
+
(ext:inet-sendto (socket usocket) buffer length (if host (host-to-hbo host)) port)))
|
|
165
|
+
|
|
166
|
+
(defmethod socket-receive ((usocket datagram-usocket) buffer length &key)
|
|
167
|
+
(let ((real-buffer (or buffer
|
|
168
|
+
(make-array length :element-type '(unsigned-byte 8))))
|
|
169
|
+
(real-length (or length
|
|
170
|
+
(length buffer))))
|
|
171
|
+
(multiple-value-bind (nbytes remote-host remote-port)
|
|
172
|
+
(with-mapped-conditions (usocket)
|
|
173
|
+
(ext:inet-recvfrom (socket usocket) real-buffer real-length))
|
|
174
|
+
(when (plusp nbytes)
|
|
175
|
+
(values real-buffer nbytes remote-host remote-port)))))
|
|
176
|
+
|
|
177
|
+
(defmethod get-local-name ((usocket usocket))
|
|
178
|
+
(multiple-value-bind
|
|
179
|
+
(address port)
|
|
180
|
+
(ext:get-socket-host-and-port (socket usocket))
|
|
181
|
+
(values (hbo-to-vector-quad address) port)))
|
|
182
|
+
|
|
183
|
+
(defmethod get-peer-name ((usocket stream-usocket))
|
|
184
|
+
(multiple-value-bind
|
|
185
|
+
(address port)
|
|
186
|
+
(ext:get-peer-host-and-port (socket usocket))
|
|
187
|
+
(values (hbo-to-vector-quad address) port)))
|
|
188
|
+
|
|
189
|
+
(defmethod get-local-address ((usocket usocket))
|
|
190
|
+
(nth-value 0 (get-local-name usocket)))
|
|
191
|
+
|
|
192
|
+
(defmethod get-peer-address ((usocket stream-usocket))
|
|
193
|
+
(nth-value 0 (get-peer-name usocket)))
|
|
194
|
+
|
|
195
|
+
(defmethod get-local-port ((usocket usocket))
|
|
196
|
+
(nth-value 1 (get-local-name usocket)))
|
|
197
|
+
|
|
198
|
+
(defmethod get-peer-port ((usocket stream-usocket))
|
|
199
|
+
(nth-value 1 (get-peer-name usocket)))
|
|
200
|
+
|
|
201
|
+
|
|
202
|
+
(defun lookup-host-entry (host)
|
|
203
|
+
(multiple-value-bind
|
|
204
|
+
(entry errno)
|
|
205
|
+
(ext:lookup-host-entry host)
|
|
206
|
+
(if entry
|
|
207
|
+
entry
|
|
208
|
+
;;###The constants below work on *most* OSes, but are defined as the
|
|
209
|
+
;; constants mentioned in C
|
|
210
|
+
(let ((exception
|
|
211
|
+
(second (assoc errno
|
|
212
|
+
'((1 ns-host-not-found-error) ;; HOST_NOT_FOUND
|
|
213
|
+
(2 ns-no-recovery-error) ;; NO_DATA
|
|
214
|
+
(3 ns-no-recovery-error) ;; NO_RECOVERY
|
|
215
|
+
(4 ns-try-again)))))) ;; TRY_AGAIN
|
|
216
|
+
(when exception
|
|
217
|
+
(error exception))))))
|
|
218
|
+
|
|
219
|
+
|
|
220
|
+
(defun get-host-by-address (address)
|
|
221
|
+
(handler-case (ext:host-entry-name
|
|
222
|
+
(lookup-host-entry (host-byte-order address)))
|
|
223
|
+
(condition (condition) (handle-condition condition))))
|
|
224
|
+
|
|
225
|
+
(defun get-hosts-by-name (name)
|
|
226
|
+
(handler-case (mapcar #'hbo-to-vector-quad
|
|
227
|
+
(ext:host-entry-addr-list
|
|
228
|
+
(lookup-host-entry name)))
|
|
229
|
+
(condition (condition) (handle-condition condition))))
|
|
230
|
+
|
|
231
|
+
(defun get-host-name ()
|
|
232
|
+
(unix:unix-gethostname))
|
|
233
|
+
|
|
234
|
+
(defun %setup-wait-list (wait-list)
|
|
235
|
+
(declare (ignore wait-list)))
|
|
236
|
+
|
|
237
|
+
(defun %add-waiter (wait-list waiter)
|
|
238
|
+
(push (socket waiter) (wait-list-%wait wait-list)))
|
|
239
|
+
|
|
240
|
+
(defun %remove-waiter (wait-list waiter)
|
|
241
|
+
(setf (wait-list-%wait wait-list)
|
|
242
|
+
(remove (socket waiter) (wait-list-%wait wait-list))))
|
|
243
|
+
|
|
244
|
+
(defun wait-for-input-internal (wait-list &key timeout)
|
|
245
|
+
(with-mapped-conditions ()
|
|
246
|
+
(alien:with-alien ((rfds (alien:struct unix:fd-set)))
|
|
247
|
+
(unix:fd-zero rfds)
|
|
248
|
+
(dolist (socket (wait-list-%wait wait-list))
|
|
249
|
+
(unix:fd-set socket rfds))
|
|
250
|
+
(multiple-value-bind
|
|
251
|
+
(secs musecs)
|
|
252
|
+
(split-timeout (or timeout 1))
|
|
253
|
+
(multiple-value-bind
|
|
254
|
+
(count err)
|
|
255
|
+
(unix:unix-fast-select (1+ (reduce #'max
|
|
256
|
+
(wait-list-%wait wait-list)))
|
|
257
|
+
(alien:addr rfds) nil nil
|
|
258
|
+
(when timeout secs) musecs)
|
|
259
|
+
(if (<= 0 count)
|
|
260
|
+
;; process the result...
|
|
261
|
+
(dolist (x (wait-list-waiters wait-list))
|
|
262
|
+
(when (unix:fd-isset (socket x) rfds)
|
|
263
|
+
(setf (state x) :READ)))
|
|
264
|
+
(progn
|
|
265
|
+
;;###FIXME generate an error, except for EINTR
|
|
266
|
+
)))))))
|