X-Git-Url: http://git.pond.sub.org/?p=eow;a=blobdiff_plain;f=empire.lisp;h=4797ac71e4817e424e26ad250c26ffab57d82ad5;hp=fa088df853f29dc7613639fa036a139ce82ddcab;hb=b3185daf3e8bc16cba79f6562694decf722dbde7;hpb=f457ab38fddc9a587b37b3d97b8bcc19d5c412cb diff --git a/empire.lisp b/empire.lisp index fa088df..4797ac7 100644 --- a/empire.lisp +++ b/empire.lisp @@ -42,7 +42,11 @@ this stream.") (connection-handler :accessor connection-handler :initform nil - :documentation "Handler function for incoming messages"))) + :documentation "Handler function for incoming messages") + (mode + :accessor connection-mode + :initform nil + :documentation "TODO(gefla)"))) (defun make-connection (&key (user nil) (password nil) @@ -93,7 +97,7 @@ this stream.") (defparameter +C_EXIT+ "3") (defparameter +C_FLUSH+ "4") (defparameter +C_NOECHO+ "5") -(defparameter +C_PROMPT+ "6") +(defparameter +C_PROMPT+ "6") (defparameter +C_ABORT+ "7") (defparameter +C_REDIR+ "8") (defparameter +C_PIPE+ "9") @@ -103,13 +107,52 @@ this stream.") (defparameter +C_FLASH+ "d") (defparameter +C_INFORM+ "e") -(defgeneric init-mode (connection message)) -(defmethod init-mode ((c connection) message) - (declare (ignorable message)) - (play c)) +(defclass base-mode () + ((connection :initarg :connection :accessor connection))) +(defclass init-mode (base-mode) + ((play-sent-p :initform nil + :documentation "Have we already sent the play command?"))) +(defclass play-mode (base-mode) nil) + +(defun make-mode (connection mode) + (make-instance mode :connection connection)) -(defvar *line-type-dispatch* - (list `(,+C_INIT+ . init-mode))) +(defgeneric set-new-mode (base-mode new-mode)) +(defmethod set-new-mode ((m base-mode) new-mode) + (let* ((c (connection m)) + (mode (make-mode c new-mode))) + (setf (connection-mode c) mode))) + +(defgeneric handle-data (base-mode message)) +(defgeneric handle-init (base-mode message)) +(defgeneric handle-prompt (base-mode message)) + +(defmethod handle-init ((m init-mode) message) + (declare (ignorable message)) + (with-slots (play-sent-p) m + (if (not play-sent-p) + (progn + (play (connection m)) + (setf play-sent-p t)) + (set-new-mode m 'play-mode)))) + +(defmethod handle-data ((m play-mode) message) + (let* ((c (connection m)) + (log (logging-stream c))) + (format log "handle-data ~a~%" message))) + +(defmethod handle-prompt ((m play-mode) message) + (let* ((c (connection m)) + (log (logging-stream c))) + (with-input-from-string (s message) + (let* ((minutes (read s)) + (btus (read s))) + (format log "[~a:~a]: ~%" minutes btus))))) + +(defparameter *line-type-dispatch* + (list `(,+C_DATA+ . handle-data) + `(,+C_INIT+ . handle-init) + `(,+C_PROMPT+ . handle-prompt))) (defun parse-server-line (line) (let* ((first-space-index @@ -121,19 +164,30 @@ this stream.") (values message message-type))) (defmethod handle-connection ((c connection)) + (setf (connection-mode c) (make-mode c 'init-mode)) (loop while (read-message c))) (defun lookup-handler (message-type) (cdr (assoc message-type *line-type-dispatch* :test 'string=))) +(define-condition no-handler (error) + ((mode :initarg :mode) + (type :initarg :type)) + (:report (lambda (condition stream) + (with-slots (mode type) condition + (format stream "No handler for ~a in mode ~a." + type mode))))) (defmethod read-message ((c connection)) (let* ((s (network-stream c)) (log (logging-stream c)) (line (read-line s))) (format log "< ~a~%" line) (multiple-value-bind (message type) (parse-server-line line) - (let ((handler (lookup-handler type))) - (funcall handler c message))) + (let ((handler (lookup-handler type)) + (mode (connection-mode c))) + (if handler + (funcall handler mode message) + (error 'no-handler :mode mode :type type)))) line)) (defmethod send-message ((c connection) message)