tabcl.lisp - clic - Clic is an command line interactive client for gopher written in Common LISP (HTM) git clone git://bitreich.org/clic/ git://hg6vgqziawt5s4dj.onion/clic/ (DIR) Log (DIR) Files (DIR) Refs (DIR) Tags (DIR) LICENSE --- tabcl.lisp (20241B) --- 1 ;;;; New ABCL networking support (replacement to old armedbear.lisp) 2 ;;;; Author: Chun Tian (binghe) 3 4 ;;;; See LICENSE for licensing information. 5 6 (in-package :usocket) 7 8 ;;; Java Classes ($*...) 9 (defvar $*boolean (jclass "boolean")) 10 (defvar $*byte (jclass "byte")) 11 (defvar $*byte[] (jclass "[B")) 12 (defvar $*int (jclass "int")) 13 (defvar $*long (jclass "long")) 14 (defvar $*|Byte| (jclass "java.lang.Byte")) 15 (defvar $*DatagramChannel (jclass "java.nio.channels.DatagramChannel")) 16 (defvar $*DatagramPacket (jclass "java.net.DatagramPacket")) 17 (defvar $*DatagramSocket (jclass "java.net.DatagramSocket")) 18 (defvar $*Inet4Address (jclass "java.net.Inet4Address")) 19 (defvar $*InetAddress (jclass "java.net.InetAddress")) 20 (defvar $*InetSocketAddress (jclass "java.net.InetSocketAddress")) 21 (defvar $*Iterator (jclass "java.util.Iterator")) 22 (defvar $*SelectableChannel (jclass "java.nio.channels.SelectableChannel")) 23 (defvar $*SelectionKey (jclass "java.nio.channels.SelectionKey")) 24 (defvar $*Selector (jclass "java.nio.channels.Selector")) 25 (defvar $*ServerSocket (jclass "java.net.ServerSocket")) 26 (defvar $*ServerSocketChannel (jclass "java.nio.channels.ServerSocketChannel")) 27 (defvar $*Set (jclass "java.util.Set")) 28 (defvar $*Socket (jclass "java.net.Socket")) 29 (defvar $*SocketAddress (jclass "java.net.SocketAddress")) 30 (defvar $*SocketChannel (jclass "java.nio.channels.SocketChannel")) 31 (defvar $*String (jclass "java.lang.String")) 32 33 ;;; Java Constructor ($%.../n) 34 (defvar $%Byte/0 (jconstructor $*|Byte| $*byte)) 35 (defvar $%DatagramPacket/3 (jconstructor $*DatagramPacket $*byte[] $*int $*int)) 36 (defvar $%DatagramPacket/5 (jconstructor $*DatagramPacket $*byte[] $*int $*int $*InetAddress $*int)) 37 (defvar $%DatagramSocket/0 (jconstructor $*DatagramSocket)) 38 (defvar $%DatagramSocket/1 (jconstructor $*DatagramSocket $*int)) 39 (defvar $%DatagramSocket/2 (jconstructor $*DatagramSocket $*int $*InetAddress)) 40 (defvar $%InetSocketAddress/1 (jconstructor $*InetSocketAddress $*int)) 41 (defvar $%InetSocketAddress/2 (jconstructor $*InetSocketAddress $*InetAddress $*int)) 42 (defvar $%ServerSocket/0 (jconstructor $*ServerSocket)) 43 (defvar $%ServerSocket/1 (jconstructor $*ServerSocket $*int)) 44 (defvar $%ServerSocket/2 (jconstructor $*ServerSocket $*int $*int)) 45 (defvar $%ServerSocket/3 (jconstructor $*ServerSocket $*int $*int $*InetAddress)) 46 (defvar $%Socket/0 (jconstructor $*Socket)) 47 (defvar $%Socket/2 (jconstructor $*Socket $*InetAddress $*int)) 48 (defvar $%Socket/4 (jconstructor $*Socket $*InetAddress $*int $*InetAddress $*int)) 49 50 ;;; Java Methods ($@...[/Class]/n) 51 (defvar $@accept/0 (jmethod $*ServerSocket "accept")) 52 (defvar $@bind/DatagramSocket/1 (jmethod $*DatagramSocket "bind" $*SocketAddress)) 53 (defvar $@bind/ServerSocket/1 (jmethod $*ServerSocket "bind" $*SocketAddress)) 54 (defvar $@bind/ServerSocket/2 (jmethod $*ServerSocket "bind" $*SocketAddress $*int)) 55 (defvar $@bind/Socket/1 (jmethod $*Socket "bind" $*SocketAddress)) 56 (defvar $@byteValue/0 (jmethod $*|Byte| "byteValue")) 57 (defvar $@channel/0 (jmethod $*SelectionKey "channel")) 58 (defvar $@close/DatagramSocket/0 (jmethod $*DatagramSocket "close")) 59 (defvar $@close/Selector/0 (jmethod $*Selector "close")) 60 (defvar $@close/ServerSocket/0 (jmethod $*ServerSocket "close")) 61 (defvar $@close/Socket/0 (jmethod $*Socket "close")) 62 (defvar $@shutdownInput/Socket/0 (jmethod $*Socket "shutdownInput")) 63 (defvar $@shutdownOutput/Socket/0 (jmethod $*Socket "shutdownOutput")) 64 (defvar $@configureBlocking/1 (jmethod $*SelectableChannel "configureBlocking" $*boolean)) 65 (defvar $@connect/DatagramChannel/1 (jmethod $*DatagramChannel "connect" $*SocketAddress)) 66 (defvar $@connect/Socket/1 (jmethod $*Socket "connect" $*SocketAddress)) 67 (defvar $@connect/Socket/2 (jmethod $*Socket "connect" $*SocketAddress $*int)) 68 (defvar $@connect/SocketChannel/1 (jmethod $*SocketChannel "connect" $*SocketAddress)) 69 (defvar $@getAddress/0 (jmethod $*InetAddress "getAddress")) 70 (defvar $@getAllByName/1 (jmethod $*InetAddress "getAllByName" $*String)) 71 (defvar $@getByName/1 (jmethod $*InetAddress "getByName" $*String)) 72 (defvar $@getChannel/DatagramSocket/0 (jmethod $*DatagramSocket "getChannel")) 73 (defvar $@getChannel/ServerSocket/0 (jmethod $*ServerSocket "getChannel")) 74 (defvar $@getChannel/Socket/0 (jmethod $*Socket "getChannel")) 75 (defvar $@getAddress/DatagramPacket/0 (jmethod $*DatagramPacket "getAddress")) 76 (defvar $@getHostName/0 (jmethod $*InetAddress "getHostName")) 77 (defvar $@getInetAddress/DatagramSocket/0 (jmethod $*DatagramSocket "getInetAddress")) 78 (defvar $@getInetAddress/ServerSocket/0 (jmethod $*ServerSocket "getInetAddress")) 79 (defvar $@getInetAddress/Socket/0 (jmethod $*Socket "getInetAddress")) 80 (defvar $@getLength/DatagramPacket/0 (jmethod $*DatagramPacket "getLength")) 81 (defvar $@getLocalAddress/DatagramSocket/0 (jmethod $*DatagramSocket "getLocalAddress")) 82 (defvar $@getLocalAddress/Socket/0 (jmethod $*Socket "getLocalAddress")) 83 (defvar $@getLocalPort/DatagramSocket/0 (jmethod $*DatagramSocket "getLocalPort")) 84 (defvar $@getLocalPort/ServerSocket/0 (jmethod $*ServerSocket "getLocalPort")) 85 (defvar $@getLocalPort/Socket/0 (jmethod $*Socket "getLocalPort")) 86 (defvar $@getOffset/DatagramPacket/0 (jmethod $*DatagramPacket "getOffset")) 87 (defvar $@getPort/DatagramPacket/0 (jmethod $*DatagramPacket "getPort")) 88 (defvar $@getPort/DatagramSocket/0 (jmethod $*DatagramSocket "getPort")) 89 (defvar $@getPort/Socket/0 (jmethod $*Socket "getPort")) 90 (defvar $@hasNext/0 (jmethod $*Iterator "hasNext")) 91 (defvar $@iterator/0 (jmethod $*Set "iterator")) 92 (defvar $@next/0 (jmethod $*Iterator "next")) 93 (defvar $@open/DatagramChannel/0 (jmethod $*DatagramChannel "open")) 94 (defvar $@open/Selector/0 (jmethod $*Selector "open")) 95 (defvar $@open/ServerSocketChannel/0 (jmethod $*ServerSocketChannel "open")) 96 (defvar $@open/SocketChannel/0 (jmethod $*SocketChannel "open")) 97 (defvar $@receive/1 (jmethod $*DatagramSocket "receive" $*DatagramPacket)) 98 (defvar $@register/2 (jmethod $*SelectableChannel "register" $*Selector $*int)) 99 (defvar $@select/0 (jmethod $*Selector "select")) 100 (defvar $@select/1 (jmethod $*Selector "select" $*long)) 101 (defvar $@selectedKeys/0 (jmethod $*Selector "selectedKeys")) 102 (defvar $@send/1 (jmethod $*DatagramSocket "send" $*DatagramPacket)) 103 (defvar $@setReuseAddress/1 (jmethod $*ServerSocket "setReuseAddress" $*boolean)) 104 (defvar $@setSoTimeout/DatagramSocket/1 (jmethod $*DatagramSocket "setSoTimeout" $*int)) 105 (defvar $@setSoTimeout/Socket/1 (jmethod $*Socket "setSoTimeout" $*int)) 106 (defvar $@setTcpNoDelay/1 (jmethod $*Socket "setTcpNoDelay" $*boolean)) 107 (defvar $@socket/DatagramChannel/0 (jmethod $*DatagramChannel "socket")) 108 (defvar $@socket/ServerSocketChannel/0 (jmethod $*ServerSocketChannel "socket")) 109 (defvar $@socket/SocketChannel/0 (jmethod $*SocketChannel "socket")) 110 (defvar $@validOps/0 (jmethod $*SelectableChannel "validOps")) 111 112 ;;; Java Field Variables ($+...) 113 (defvar $+op-accept (jfield $*SelectionKey "OP_ACCEPT")) 114 (defvar $+op-connect (jfield $*SelectionKey "OP_CONNECT")) 115 (defvar $+op-read (jfield $*SelectionKey "OP_READ")) 116 (defvar $+op-write (jfield $*SelectionKey "OP_WRITE")) 117 118 119 ;;; Wrapper functions (return-type: java-object) 120 (defun %get-address (address) 121 (jcall $@getAddress/0 address)) 122 (defun %get-all-by-name (string) ; return a simple vector 123 (jstatic $@getAllByName/1 $*InetAddress string)) 124 (defun %get-by-name (string) 125 (jstatic $@getByName/1 $*InetAddress string)) 126 127 (defun host-to-inet4 (host) 128 "USOCKET host formats to Java Inet4Address, used internally." 129 (%get-by-name (host-to-hostname host))) 130 131 ;;; HANDLE-CONTITION 132 133 (defparameter +abcl-error-map+ 134 `(("java.net.BindException" . operation-not-permitted-error) 135 ("java.net.ConnectException" . connection-refused-error) 136 ("java.net.NoRouteToHostException" . network-unreachable-error) ; untested 137 ("java.net.PortUnreachableException" . protocol-not-supported-error) ; untested 138 ("java.net.ProtocolException" . protocol-not-supported-error) ; untested 139 ("java.net.SocketException" . socket-type-not-supported-error) ; untested 140 ("java.net.SocketTimeoutException" . timeout-error))) 141 142 (defparameter +abcl-nameserver-error-map+ 143 `(("java.net.UnknownHostException" . ns-host-not-found-error))) 144 145 (defun handle-condition (condition &optional (socket nil)) 146 (typecase condition 147 (java-exception 148 (let ((java-cause (java-exception-cause condition))) 149 (let* ((usock-error (cdr (assoc (jclass-of java-cause) +abcl-error-map+ 150 :test #'string=))) 151 (usock-error (if (functionp usock-error) 152 (funcall usock-error condition) 153 usock-error)) 154 (nameserver-error (cdr (assoc (jclass-of java-cause) +abcl-nameserver-error-map+ 155 :test #'string=)))) 156 (if nameserver-error 157 (error nameserver-error :host-or-ip nil) 158 (when usock-error 159 (error usock-error :socket socket)))))))) 160 161 ;;; GET-HOSTS-BY-NAME 162 163 (defun get-address (address) 164 (when address 165 (let* ((array (%get-address address)) 166 (length (jarray-length array))) 167 (labels ((jbyte (n) 168 (let ((byte (jarray-ref array n))) 169 (if (minusp byte) (+ 256 byte) byte)))) 170 (cond 171 ((= 4 length) 172 (vector (jbyte 0) (jbyte 1) (jbyte 2) (jbyte 3))) 173 ((= 16 length) 174 (vector (jbyte 0) (jbyte 1) (jbyte 2) (jbyte 3) 175 (jbyte 4) (jbyte 5) (jbyte 6) (jbyte 7) 176 (jbyte 8) (jbyte 9) (jbyte 10) (jbyte 11) 177 (jbyte 12) (jbyte 13) (jbyte 14) (jbyte 15))) 178 (t nil)))))) ; neither a IPv4 nor IPv6 address?! 179 180 (defun get-hosts-by-name (name) 181 (with-mapped-conditions () 182 (map 'list #'get-address (%get-all-by-name name)))) 183 184 ;;; GET-HOST-BY-ADDRESS 185 186 (defun get-host-by-address (host) 187 (let ((inet4 (host-to-inet4 host))) 188 (with-mapped-conditions () 189 (jcall $@getHostName/0 inet4)))) 190 191 ;;; SOCKET-CONNECT 192 193 (defun socket-connect (host port &key (protocol :stream) (element-type 'character) 194 timeout deadline (nodelay t nodelay-supplied-p) 195 local-host local-port) 196 (when deadline (unsupported 'deadline 'socket-connect)) 197 (let (socket stream usocket) 198 (ecase protocol 199 (:stream ; TCP 200 (let ((channel (jstatic $@open/SocketChannel/0 $*SocketChannel)) 201 (address (jnew $%InetSocketAddress/2 (host-to-inet4 host) port))) 202 (setq socket (jcall $@socket/SocketChannel/0 channel)) 203 ;; bind to local address if needed 204 (when (or local-host local-port) 205 (let ((local-address (jnew $%InetSocketAddress/2 (host-to-inet4 local-host) (or local-port 0)))) 206 (with-mapped-conditions () 207 (jcall $@bind/Socket/1 socket local-address)))) 208 ;; connect to dest address 209 (with-mapped-conditions () 210 (jcall $@connect/SocketChannel/1 channel address)) 211 (setq stream (ext:get-socket-stream socket :element-type element-type) 212 usocket (make-stream-socket :stream stream :socket socket)) 213 (when nodelay-supplied-p 214 (jcall $@setTcpNoDelay/1 socket (if nodelay ;; both t and :if-supported mean java:+true+ 215 java:+true+ java:+false+))) 216 (when timeout 217 (jcall $@setSoTimeout/Socket/1 socket (truncate (* 1000 timeout)))))) 218 (:datagram ; UDP 219 (let ((channel (jstatic $@open/DatagramChannel/0 $*DatagramChannel))) 220 (setq socket (jcall $@socket/DatagramChannel/0 channel)) 221 ;; bind to local address if needed 222 (when (or local-host local-port) 223 (let ((local-address (jnew $%InetSocketAddress/2 (host-to-inet4 local-host) (or local-port 0)))) 224 (with-mapped-conditions () 225 (jcall $@bind/DatagramSocket/1 socket local-address)))) 226 ;; connect to dest address if needed 227 (when (and host port) 228 (let ((address (jnew $%InetSocketAddress/2 (host-to-inet4 host) port))) 229 (with-mapped-conditions () 230 (jcall $@connect/DatagramChannel/1 channel address)))) 231 (setq usocket (make-datagram-socket socket :connected-p (if (and host port) t nil))) 232 (when timeout 233 (jcall $@setSoTimeout/DatagramSocket/1 socket (truncate (* 1000 timeout))))))) 234 usocket)) 235 236 ;;; SOCKET-LISTEN 237 238 (defun socket-listen (host port &key reuseaddress 239 (reuse-address nil reuse-address-supplied-p) 240 (backlog 5 backlog-supplied-p) 241 (element-type 'character)) 242 (declare (type boolean reuse-address)) 243 (let* ((reuseaddress (if reuse-address-supplied-p reuse-address reuseaddress)) 244 (channel (jstatic $@open/ServerSocketChannel/0 $*ServerSocketChannel)) 245 (socket (jcall $@socket/ServerSocketChannel/0 channel)) 246 (endpoint (jnew $%InetSocketAddress/2 (host-to-inet4 host) (or port 0)))) 247 (jcall $@setReuseAddress/1 socket (if reuseaddress java:+true+ java:+false+)) 248 (with-mapped-conditions (socket) 249 (if backlog-supplied-p 250 (jcall $@bind/ServerSocket/2 socket endpoint backlog) 251 (jcall $@bind/ServerSocket/1 socket endpoint))) 252 (make-stream-server-socket socket :element-type element-type))) 253 254 ;;; SOCKET-ACCEPT 255 256 (defmethod socket-accept ((usocket stream-server-usocket) 257 &key (element-type 'character element-type-p)) 258 (with-mapped-conditions (usocket) 259 (let* ((client-socket (jcall $@accept/0 (socket usocket))) 260 (element-type (if element-type-p 261 element-type 262 (element-type usocket))) 263 (stream (ext:get-socket-stream client-socket :element-type element-type))) 264 (make-stream-socket :stream stream :socket client-socket)))) 265 266 ;;; SOCKET-CLOSE 267 268 (defmethod socket-close :before ((usocket usocket)) 269 (when (wait-list usocket) 270 (remove-waiter (wait-list usocket) usocket))) 271 272 (defmethod socket-close ((usocket stream-server-usocket)) 273 (with-mapped-conditions (usocket) 274 (jcall $@close/ServerSocket/0 (socket usocket)))) 275 276 (defmethod socket-close ((usocket stream-usocket)) 277 (with-mapped-conditions (usocket) 278 (close (socket-stream usocket)) 279 (jcall $@close/Socket/0 (socket usocket)))) 280 281 (defmethod socket-close ((usocket datagram-usocket)) 282 (with-mapped-conditions (usocket) 283 (jcall $@close/DatagramSocket/0 (socket usocket)))) 284 285 (defmethod socket-shutdown ((usocket stream-usocket) direction) 286 (with-mapped-conditions (usocket) 287 (ecase direction 288 (:input 289 (jcall $@shutdownInput/Socket/0 (socket usocket))) 290 (:output 291 (jcall $@shutdownOutput/Socket/0 (socket usocket)))))) 292 293 ;;; GET-LOCAL/PEER-NAME/ADDRESS/PORT 294 295 (defmethod get-local-name ((usocket usocket)) 296 (values (get-local-address usocket) 297 (get-local-port usocket))) 298 299 (defmethod get-peer-name ((usocket usocket)) 300 (values (get-peer-address usocket) 301 (get-peer-port usocket))) 302 303 (defmethod get-local-address ((usocket stream-usocket)) 304 (get-address (jcall $@getLocalAddress/Socket/0 (socket usocket)))) 305 306 (defmethod get-local-address ((usocket stream-server-usocket)) 307 (get-address (jcall $@getInetAddress/ServerSocket/0 (socket usocket)))) 308 309 (defmethod get-local-address ((usocket datagram-usocket)) 310 (get-address (jcall $@getLocalAddress/DatagramSocket/0 (socket usocket)))) 311 312 (defmethod get-peer-address ((usocket stream-usocket)) 313 (get-address (jcall $@getInetAddress/Socket/0 (socket usocket)))) 314 315 (defmethod get-peer-address ((usocket datagram-usocket)) 316 (get-address (jcall $@getInetAddress/DatagramSocket/0 (socket usocket)))) 317 318 (defmethod get-local-port ((usocket stream-usocket)) 319 (jcall $@getLocalPort/Socket/0 (socket usocket))) 320 321 (defmethod get-local-port ((usocket stream-server-usocket)) 322 (jcall $@getLocalPort/ServerSocket/0 (socket usocket))) 323 324 (defmethod get-local-port ((usocket datagram-usocket)) 325 (jcall $@getLocalPort/DatagramSocket/0 (socket usocket))) 326 327 (defmethod get-peer-port ((usocket stream-usocket)) 328 (jcall $@getPort/Socket/0 (socket usocket))) 329 330 (defmethod get-peer-port ((usocket datagram-usocket)) 331 (jcall $@getPort/DatagramSocket/0 (socket usocket))) 332 333 ;;; SOCKET-SEND & SOCKET-RECEIVE 334 335 (defun *->byte (data) 336 (declare (type (unsigned-byte 8) data)) ; required by SOCKET-SEND 337 (jnew $%Byte/0 (if (> data 127) (- data 256) data))) 338 339 (defun byte->* (byte &optional (element-type '(unsigned-byte 8))) 340 (let* ((ub8 (if (minusp byte) (+ 256 byte) byte))) 341 (if (eq element-type 'character) 342 (code-char ub8) 343 ub8))) 344 345 (defmethod socket-send ((usocket datagram-usocket) buffer size &key host port (offset 0)) 346 (let* ((socket (socket usocket)) 347 (byte-array (jnew-array $*byte size)) 348 (packet (if (and host port) 349 (jnew $%DatagramPacket/5 byte-array 0 size (host-to-inet4 host) port) 350 (jnew $%DatagramPacket/3 byte-array 0 size)))) 351 ;; prepare sending data 352 (loop for i from offset below (+ size offset) 353 do (setf (jarray-ref byte-array i) (*->byte (aref buffer i)))) 354 (with-mapped-conditions (usocket) 355 (jcall $@send/1 socket packet)))) 356 357 ;;; TODO: return-host and return-port cannot be get ... 358 (defmethod socket-receive ((usocket datagram-usocket) buffer length 359 &key (element-type '(unsigned-byte 8))) 360 (declare (values (simple-array (unsigned-byte 8) (*)) ; buffer 361 (integer 0) ; size 362 (unsigned-byte 32) ; host 363 (unsigned-byte 16))) ; port 364 (let* ((socket (socket usocket)) 365 (real-length (or length +max-datagram-packet-size+)) 366 (byte-array (jnew-array $*byte real-length)) 367 (packet (jnew $%DatagramPacket/3 byte-array 0 real-length))) 368 (with-mapped-conditions (usocket) 369 (jcall $@receive/1 socket packet)) 370 (let* ((receive-length (jcall $@getLength/DatagramPacket/0 packet)) 371 (return-buffer (or buffer (make-array receive-length :element-type element-type)))) 372 (loop for i from 0 below receive-length 373 do (setf (aref return-buffer i) 374 (byte->* (jarray-ref byte-array i) element-type))) 375 (let ((return-host (if (connected-p usocket) 376 (get-peer-address usocket) 377 (get-address (jcall $@getAddress/DatagramPacket/0 packet)))) 378 (return-port (if (connected-p usocket) 379 (get-peer-port usocket) 380 (jcall $@getPort/DatagramPacket/0 packet)))) 381 (values return-buffer 382 receive-length 383 return-host 384 return-port))))) 385 386 ;;; WAIT-FOR-INPUT 387 388 (defun socket-channel-class (usocket) 389 (cond ((stream-usocket-p usocket) $*SocketChannel) 390 ((stream-server-usocket-p usocket) $*ServerSocketChannel) 391 ((datagram-usocket-p usocket) $*DatagramChannel))) 392 393 (defun get-socket-channel (usocket) 394 (let ((method (cond ((stream-usocket-p usocket) $@getChannel/Socket/0) 395 ((stream-server-usocket-p usocket) $@getChannel/ServerSocket/0) 396 ((datagram-usocket-p usocket) $@getChannel/DatagramSocket/0)))) 397 (jcall method (socket usocket)))) 398 399 (defun wait-for-input-internal (wait-list &key timeout) 400 (let* ((sockets (wait-list-waiters wait-list)) 401 (ops (logior $+op-read $+op-accept)) 402 (selector (jstatic $@open/Selector/0 $*Selector)) 403 (channels (mapcar #'get-socket-channel sockets))) 404 (unwind-protect 405 (with-mapped-conditions () 406 (dolist (channel channels) 407 (jcall $@configureBlocking/1 channel java:+false+) 408 (jcall $@register/2 channel selector (logand ops (jcall $@validOps/0 channel)))) 409 (let ((ready-count (if timeout 410 (jcall $@select/1 selector (truncate (* timeout 1000))) 411 (jcall $@select/0 selector)))) 412 (when (plusp ready-count) 413 (let* ((keys (jcall $@selectedKeys/0 selector)) 414 (iterator (jcall $@iterator/0 keys)) 415 (%wait (wait-list-%wait wait-list))) 416 (loop while (jcall $@hasNext/0 iterator) 417 do (let* ((key (jcall $@next/0 iterator)) 418 (channel (jcall $@channel/0 key))) 419 (setf (state (gethash channel %wait)) :read))))))) 420 (jcall $@close/Selector/0 selector) 421 (dolist (channel channels) 422 (jcall $@configureBlocking/1 channel java:+true+))))) 423 424 ;;; WAIT-LIST 425 426 ;;; NOTE from original worker (Erik): 427 ;;; Note that even though Java has the concept of the Selector class, which 428 ;;; remotely looks like a wait-list, it requires the sockets to be non-blocking. 429 ;;; usocket however doesn't make any such guarantees and is therefore unable to 430 ;;; use the concept outside of the waiting routine itself (blergh!). 431 432 (defun %setup-wait-list (wl) 433 (setf (wait-list-%wait wl) 434 (make-hash-table :test #'equal :rehash-size 1.3d0))) 435 436 (defun %add-waiter (wl w) 437 (setf (gethash (get-socket-channel w) (wait-list-%wait wl)) w)) 438 439 (defun %remove-waiter (wl w) 440 (remhash (get-socket-channel w) (wait-list-%wait wl)))