;;; -*- Mode: LISP; Package: CGP; BASE: 10; Syntax: ANSI-Common-Lisp; -*- (in-package "CGP") ;; *** change to actual location of "xopentransport.lisp" #-cl-http (load "http:mcl;server;xopentransport") ;; fix for #\LF as end-line char in Windows #+mcl (let ((ccl::*warn-if-redefine-kernel* nil)) (defmethod ccl::read-line-raw ((input-stream t) eof-error-p eof-value) "A faster way to do read-line-raw than that in streams.lisp. The speedup comes from avoiding with-output-to-string. Conses less too." (declare (optimize (speed 3) (safety 1))) (if (ccl::stream-eofp input-stream) (if eof-error-p (error 'ccl::end-of-file :stream input-stream) (values eof-value (or eof-value t))) (let ((char nil) (str (make-array 20 :element-type 'base-character :adjustable t :fill-pointer 0))) (multiple-value-bind (reader reader-arg) (ccl::stream-reader input-stream) (ccl::while (and (setq char (funcall reader reader-arg)) (ccl::neq char #\CR) (ccl::neq char #\LF)) (when (and (not (ccl::base-character-p char))(ccl::base-string-p str)) (setq str (ccl::string-to-extended-string str))) (vector-push-extend char str))) (values str (null char)))))) ;(tcp-addr-to-str (tcp-host-address "cmc.uib.no")) (defparameter *port* 4028) ;(defparameter *magic-string* "Hello-CGP!") (defparameter *remote-ip-address* "gandalf.hit.uib.no") (defparameter *cgp-stream* (ccl::open-tcp-stream nil *port* :element-type 'base-character :connect-timeout 30000)) ;; Read-eval-send loop receiving forms (e.g. strings) to process. ;; STREAM is a listening active tcp-stream. When the MOO server connects, PROCESS-cgp-CALL ;; first checks if the remote host is allowed to connect (by comparing IP addresses; could ;; also be password check) and either closes the connection or waits for input. ;; Each time a line is read, that line is processed by FUN (in (FUNCALL FUN FORM)), and the ;; result is written back to the stream. The magic string sent afterwards tells cgp that ;; all input has arrived. (defun process-cgp-call (fun &optional (stream *cgp-stream*) accepted-p) (case (ccl::stream-connection-state-name stream) (:established (cond (accepted-p (handler-case (let ((line (read-line stream nil :eof))) (unless (or (eq line :eof) (string= line "") (string= line #.(format nil "~a" #\CR)) (string= line #.(format nil "~a" #\LF))) (FUNCALL FUN LINE stream) ;(print (FUNCALL FUN LINE) stream) ;(write-char #\LF stream) ; write Windows CR+LF ; (write-line *magic-string* stream) (write-char #\LF stream) (force-output stream)) (process-cgp-call fun stream accepted-p)) (ccl::connection-lost () ;; ignore error (print "connection lost")) (ccl::connection-closed () ;; ignore error (print "connection closed")))) ((= (ccl::tcp-host-address *remote-ip-address*) (ccl::stream-remote-host stream)) ;; accepted (process-cgp-call fun stream t)) (t (print "connection refused") (close stream :abort t) (let ((stream (ccl::open-tcp-stream nil *port* :element-type 'base-character))) (setf *cgp-stream* stream) (process-cgp-call fun stream))))) ((:closing :closed :idle) (close stream) ;; reopen stream and listen (let ((stream (ccl::open-tcp-stream nil *port* :element-type 'base-character))) (setf *cgp-stream* stream) (process-cgp-call fun stream))) (t (sleep 0.1) (process-cgp-call fun stream)))) #+test (close *cgp-stream*) #+test (ccl::stream-connection-state-name *cgp-stream*) #+test (ccl::process-run-function "cgp-eval-loop" 'process-cgp-call ;(lambda (line) line) #'disambiguate-line #+ignore(lambda (line) (eval (read-from-string line)))) (defun disambiguate-line (line stream) (print line) (disambiguate-from-string line :stream stream :unix-p t))