3 ;;; **********************************************************************
4 ;;; This code was written by Paul Foley and has been placed in the public
8 ;;; Sbcl port by Rudi Schlatte.
10 (in-package "SB-SIMPLE-STREAMS")
13 ;;; **********************************************************************
15 ;;; Socket-simple-stream and socket-base-simple-stream
17 (def-stream-class socket-simple-stream (dual-channel-simple-stream)
18 (;; keep the socket around; it could be handy e.g. for querying peer
20 (socket :initform nil :type (or sb-bsd-sockets:socket null)
23 (defmethod print-object ((object socket-simple-stream) stream)
24 (print-unreadable-object (object stream :type nil :identity nil)
25 (with-stream-class (socket-simple-stream object)
26 (cond ((not (any-stream-instance-flags object :simple))
27 (princ "Invalid " stream))
28 ((not (any-stream-instance-flags object :input :output))
29 (princ "Closed " stream)))
30 (format stream "~:(~A~)"
32 (when (any-stream-instance-flags object :input :output)
33 (multiple-value-bind (host port)
34 (sb-bsd-sockets:socket-peername (sm socket object))
35 (format stream " connected to host ~S, port ~S" host port))))))
37 (def-stream-class socket-base-simple-stream (dual-channel-simple-stream)
40 (defmethod device-open ((stream socket-simple-stream) options)
41 (let* ((remote-host (getf options :remote-host))
42 (remote-port (getf options :remote-port))
43 (socket (make-instance 'sb-bsd-sockets:inet-socket
44 :type :stream :protocol :tcp)))
45 (unless (and remote-host remote-port)
46 (error "device-open on ~S requires :remote-host and :remote-port arguments"
47 'socket-simple-stream))
48 (with-stream-class (socket-simple-stream stream)
49 (ecase (getf options :direction :input)
50 (:input (add-stream-instance-flags stream :input))
51 (:output (add-stream-instance-flags stream :output))
52 (:io (add-stream-instance-flags stream :input :output)))
53 (setf (sm socket stream) socket)
54 (sb-bsd-sockets:socket-connect socket remote-host remote-port)
55 (let ((fd (sb-bsd-sockets:socket-file-descriptor socket)))
57 (add-stream-instance-flags stream :dual :simple)
58 (when (any-stream-instance-flags stream :input)
59 (setf (sm input-handle stream) fd)
60 (unless (sm buffer stream)
61 (let ((length (device-buffer-length stream)))
62 (setf (sm buffer stream) (allocate-buffer length)
64 (sm buffer-ptr stream) 0
65 (sm buf-len stream) length))))
66 (when (any-stream-instance-flags stream :output)
67 (setf (sm output-handle stream) fd)
68 (unless (sm out-buffer stream)
69 (let ((length (device-buffer-length stream)))
70 (setf (sm out-buffer stream) (allocate-buffer length)
72 (sm max-out-pos stream) length)))
73 (setf (sm control-out stream) *std-control-out-table*))
74 (sb-ext:cancel-finalization socket)
75 (sb-ext:finalize stream
77 (sb-unix:unix-close fd)
79 "~&;;; ** closed socket (fd ~D)~%" fd)))
80 ;; this should be done with (setf stream-external-format)
81 (let ((efmt (getf options :external-format :default)))
82 (compose-encapsulating-streams stream efmt)
83 (install-dual-channel-character-strategy (melding-stream stream)
87 (defmethod device-close ((stream socket-simple-stream) abort)
88 (with-stream-class (socket-simple-stream stream)
89 (sb-unix:unix-close (or (sm input-handle stream)
90 (sm output-handle stream)))
91 (when (sm buffer stream)
92 (free-buffer (sm buffer stream))
93 (setf (sm buffer stream) nil))
94 (when (sm out-buffer stream)
95 (free-buffer (sm out-buffer stream))
96 (setf (sm out-buffer stream) nil))
97 (sb-ext:cancel-finalization stream)
100 (defmethod device-open ((stream socket-base-simple-stream) options)
104 (defmethod device-write ((stream socket-base-simple-stream) buffer