twait-for-input.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
       ---
       twait-for-input.lisp (4963B)
       ---
            1 ;;;; See LICENSE for licensing information.
            2 
            3 (in-package :usocket-test)
            4 
            5 (eval-when (:compile-toplevel :load-toplevel :execute)
            6   (defparameter *wait-for-input-timeout* 2))
            7 
            8 (deftest wait-for-input.1
            9   (with-caught-conditions (nil nil)
           10     (let ((sock (usocket:socket-connect *common-lisp-net* 80))
           11           (time (get-universal-time)))
           12       (unwind-protect
           13           (progn (usocket:wait-for-input sock :timeout *wait-for-input-timeout*)
           14             (- (get-universal-time) time))
           15         (usocket:socket-close sock))))
           16   #.*wait-for-input-timeout*)
           17 
           18 (deftest wait-for-input.2
           19   (with-caught-conditions (nil nil)
           20     (let ((sock (usocket:socket-connect *common-lisp-net* 80))
           21           (time (get-universal-time)))
           22       (unwind-protect
           23           (progn (usocket:wait-for-input sock :timeout *wait-for-input-timeout* :ready-only t)
           24             (- (get-universal-time) time))
           25         (usocket:socket-close sock))))
           26   #.*wait-for-input-timeout*)
           27 
           28 (deftest wait-for-input.3
           29   (with-caught-conditions (nil nil)
           30     (let ((sock (usocket:socket-connect *common-lisp-net* 80)))
           31       (unwind-protect
           32           (progn
           33             (format (usocket:socket-stream sock)
           34                     "GET / HTTP/1.0~2%")
           35             (force-output (usocket:socket-stream sock))
           36             (usocket:wait-for-input sock :timeout *wait-for-input-timeout*)
           37             (subseq (read-line (usocket:socket-stream sock)) 0 4))
           38         (usocket:socket-close sock))))
           39   "HTTP")
           40 
           41 ;;; Advanced W-F-I tests by Elliott Slaughter <elliottslaughter@gmail.com>
           42 
           43 (defvar *socket-server-port* 0)
           44 (defvar *socket-server-listen* nil)
           45 (defvar *socket-server-connection*)
           46 (defvar *socket-client-connection*)
           47 (defvar *output-p* t)
           48 
           49 (defun stage-1 ()
           50   (unless *socket-server-listen*
           51     (setf *socket-server-listen*
           52           (socket-listen *wildcard-host* 0 :element-type '(unsigned-byte 8)))
           53     (setf *socket-server-port* (get-local-port *socket-server-listen*)))
           54 
           55   (setf *socket-server-connection*
           56         (when (wait-for-input *socket-server-listen* :timeout 0 :ready-only t)
           57           (socket-accept *socket-server-listen*)))
           58   
           59   (when *output-p* ; should be NIL
           60     (format t "First time (before client connects) is ~s.~%"
           61             *socket-server-connection*))
           62 
           63   *socket-server-connection*)
           64 
           65 ;; TODO: original test code have addition (:TIMEOUT 0) when doing the SOCKET-CONNECT,
           66 ;; it seems cannot work on SBCL/Windows, need to investigate, but here we ignore it.
           67 
           68 (defun stage-2 ()
           69   (setf *socket-client-connection*
           70         (socket-connect "localhost" *socket-server-port* :protocol :stream
           71                          :element-type '(unsigned-byte 8)))
           72   (setf *socket-server-connection*
           73         (when (wait-for-input *socket-server-listen* :timeout 0 :ready-only t)
           74           #+(and win32 (or lispworks ecl sbcl))
           75           (when *output-p*
           76             (format t "%READY-P: ~D~%" (usocket::%ready-p *socket-server-listen*)))
           77           (socket-accept *socket-server-listen*)))
           78 
           79   (when *output-p* ; should be a usocket object
           80     (format t "Second time (after client connects) is ~s.~%"
           81             *socket-server-connection*))
           82 
           83   *socket-server-connection*)
           84 
           85 (defun stage-3 ()
           86   (setf *socket-server-connection*
           87         (when (wait-for-input *socket-server-listen* :timeout 0 :ready-only t)
           88           #+(and win32 (or lispworks ecl sbcl))
           89           (when *output-p*
           90             (format t "%READY-P: ~D~%" (usocket::%ready-p *socket-server-listen*)))
           91           (socket-accept *socket-server-listen*)))
           92 
           93   (when *output-p* ; should be NIL again
           94     (format t "Third time (before second client) is ~s.~%"
           95             *socket-server-connection*))
           96 
           97   *socket-server-connection*)
           98 
           99 (deftest elliott-slaughter.1
          100     (let ((*output-p* nil))
          101       (let* ((s-1 (stage-1)) (s-2 (stage-2)) (s-3 (stage-3)))
          102         (prog1 (and (null s-1) (usocket::usocket-p s-2) (null s-3))
          103           (socket-close *socket-server-listen*)
          104           (setf *socket-server-listen* nil))))
          105   t)
          106 
          107 #|
          108 
          109 Issue elliott-slaughter.2 (WAIT-FOR-INPUT/win32 on TCP socket)
          110 
          111 W-F-I correctly found the inputs, but :READY-ONLY didn't work.
          112 
          113 |#
          114 (defun receive-each (connections)
          115   (let ((ready (usocket:wait-for-input connections :timeout 0 :ready-only t)))
          116     (loop for connection in ready
          117        collect (read-line (usocket:socket-stream connection)))))
          118 
          119 (defun receive-all (connections)
          120   (loop for messages = (receive-each connections)
          121      then (receive-each connections)
          122      while messages append messages))
          123 
          124 (defun send (connection message)
          125   (format (usocket:socket-stream connection) "~a~%" message)
          126   (force-output (usocket:socket-stream connection)))
          127 
          128 (defun server ()
          129   (let* ((listen (usocket:socket-listen usocket:*wildcard-host* 12345))
          130          (connection (usocket:socket-accept listen)))
          131     (loop for messages = (receive-all connection) then (receive-all connection)
          132        do (format t "Got messages:~%~s~%" messages)
          133        do (sleep 1/50))))
          134 
          135 (defun client ()
          136   (let ((connection (usocket:socket-connect "localhost" 12345)))
          137     (loop for i from 0
          138        do (send connection (format nil "This is message ~a." i))
          139        do (sleep 1/100))))