138 lines
5.5 KiB
Common Lisp
138 lines
5.5 KiB
Common Lisp
|
|
;;;
|
||
|
|
;;; Low-level networking implementations
|
||
|
|
;;;
|
||
|
|
|
||
|
|
(in-package #:ql-network)
|
||
|
|
|
||
|
|
(definterface host-address (host)
|
||
|
|
(:implementation t
|
||
|
|
host)
|
||
|
|
(:implementation sbcl
|
||
|
|
(ql-sbcl:host-ent-address (ql-sbcl:get-host-by-name host))))
|
||
|
|
|
||
|
|
(definterface open-connection (host port)
|
||
|
|
(:documentation "Open and return a network connection to HOST on the
|
||
|
|
given PORT.")
|
||
|
|
(:implementation t
|
||
|
|
(declare (ignore host port))
|
||
|
|
(error "Sorry, quicklisp in implementation ~S is not supported yet."
|
||
|
|
(lisp-implementation-type)))
|
||
|
|
(:implementation allegro
|
||
|
|
(ql-allegro:make-socket :remote-host host
|
||
|
|
:remote-port port))
|
||
|
|
(:implementation abcl
|
||
|
|
(let ((socket (ql-abcl:make-socket host port)))
|
||
|
|
(ql-abcl:get-socket-stream socket :element-type '(unsigned-byte 8))))
|
||
|
|
(:implementation ccl
|
||
|
|
(ql-ccl:make-socket :remote-host host
|
||
|
|
:remote-port port))
|
||
|
|
(:implementation clasp
|
||
|
|
(let* ((endpoint (ql-clasp:host-ent-address
|
||
|
|
(ql-clasp:get-host-by-name host)))
|
||
|
|
(socket (make-instance 'ql-clasp:inet-socket
|
||
|
|
:protocol :tcp
|
||
|
|
:type :stream)))
|
||
|
|
(ql-clasp:socket-connect socket endpoint port)
|
||
|
|
(ql-clasp:socket-make-stream socket
|
||
|
|
:element-type '(unsigned-byte 8)
|
||
|
|
:input t
|
||
|
|
:output t
|
||
|
|
:buffering :full)))
|
||
|
|
(:implementation clisp
|
||
|
|
(ql-clisp:socket-connect port host :element-type '(unsigned-byte 8)))
|
||
|
|
(:implementation cmucl
|
||
|
|
(let ((fd (ql-cmucl:connect-to-inet-socket host port)))
|
||
|
|
(ql-cmucl:make-fd-stream fd
|
||
|
|
:element-type '(unsigned-byte 8)
|
||
|
|
:binary-stream-p t
|
||
|
|
:input t
|
||
|
|
:output t)))
|
||
|
|
(:implementation scl
|
||
|
|
(let ((fd (ql-scl:connect-to-inet-socket host port)))
|
||
|
|
(ql-scl:make-fd-stream fd
|
||
|
|
:element-type '(unsigned-byte 8)
|
||
|
|
:input t
|
||
|
|
:output t)))
|
||
|
|
(:implementation ecl
|
||
|
|
(let* ((endpoint (ql-ecl:host-ent-address
|
||
|
|
(ql-ecl:get-host-by-name host)))
|
||
|
|
(socket (make-instance 'ql-ecl:inet-socket
|
||
|
|
:protocol :tcp
|
||
|
|
:type :stream)))
|
||
|
|
(ql-ecl:socket-connect socket endpoint port)
|
||
|
|
(ql-ecl:socket-make-stream socket
|
||
|
|
:element-type '(unsigned-byte 8)
|
||
|
|
:input t
|
||
|
|
:output t
|
||
|
|
:buffering :full)))
|
||
|
|
(:implementation mkcl
|
||
|
|
(let* ((endpoint (ql-mkcl:host-ent-address
|
||
|
|
(ql-mkcl:get-host-by-name host)))
|
||
|
|
(socket (make-instance 'ql-mkcl:inet-socket
|
||
|
|
:protocol :tcp
|
||
|
|
:type :stream)))
|
||
|
|
(ql-mkcl:socket-connect socket endpoint port)
|
||
|
|
(ql-mkcl:socket-make-stream socket
|
||
|
|
:element-type '(unsigned-byte 8)
|
||
|
|
:input t
|
||
|
|
:output t
|
||
|
|
:buffering :full)))
|
||
|
|
(:implementation lispworks
|
||
|
|
(ql-lispworks:open-tcp-stream host port
|
||
|
|
:direction :io
|
||
|
|
:errorp t
|
||
|
|
:read-timeout nil
|
||
|
|
:element-type '(unsigned-byte 8)
|
||
|
|
:timeout 5))
|
||
|
|
(:implementation sbcl
|
||
|
|
(let* ((endpoint (ql-sbcl:host-ent-address
|
||
|
|
(ql-sbcl:get-host-by-name host)))
|
||
|
|
(socket (make-instance 'ql-sbcl:inet-socket
|
||
|
|
:protocol :tcp
|
||
|
|
:type :stream)))
|
||
|
|
(ql-sbcl:socket-connect socket endpoint port)
|
||
|
|
(ql-sbcl:socket-make-stream socket
|
||
|
|
:element-type '(unsigned-byte 8)
|
||
|
|
:input t
|
||
|
|
:output t
|
||
|
|
:buffering :full))))
|
||
|
|
|
||
|
|
(definterface read-octets (buffer connection)
|
||
|
|
(:documentation "Read from CONNECTION into BUFFER. Returns the
|
||
|
|
number of octets read.")
|
||
|
|
(:implementation t
|
||
|
|
(read-sequence buffer connection))
|
||
|
|
(:implementation allegro
|
||
|
|
(ql-allegro:read-vector buffer connection))
|
||
|
|
(:implementation clisp
|
||
|
|
(ql-clisp:read-byte-sequence buffer connection
|
||
|
|
:no-hang nil
|
||
|
|
:interactive t)))
|
||
|
|
|
||
|
|
(definterface write-octets (buffer connection)
|
||
|
|
(:documentation "Write the contents of BUFFER to CONNECTION.")
|
||
|
|
(:implementation t
|
||
|
|
(write-sequence buffer connection)
|
||
|
|
(finish-output connection)))
|
||
|
|
|
||
|
|
(definterface close-connection (connection)
|
||
|
|
(:implementation t
|
||
|
|
(ignore-errors (close connection))))
|
||
|
|
|
||
|
|
(definterface call-with-connection (host port fun)
|
||
|
|
(:documentation "Establish a network connection to HOST on PORT and
|
||
|
|
call FUN with that connection as the only argument. Unconditionally
|
||
|
|
closes the connection afterwareds via CLOSE-CONNECTION in an
|
||
|
|
unwind-protect. See also WITH-CONNECTION.")
|
||
|
|
(:implementation t
|
||
|
|
(let (connection)
|
||
|
|
(unwind-protect
|
||
|
|
(progn
|
||
|
|
(setf connection (open-connection host port))
|
||
|
|
(funcall fun connection))
|
||
|
|
(when connection
|
||
|
|
(close-connection connection))))))
|
||
|
|
|
||
|
|
(defmacro with-connection ((connection host port) &body body)
|
||
|
|
`(call-with-connection ,host ,port (lambda (,connection) ,@body)))
|