-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
4 changed files
with
114 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,97 @@ | ||
(in-package :mortar-combat) | ||
|
||
|
||
(define-constant +supported-server-version+ 1) | ||
|
||
(declaim (special *message*)) | ||
|
||
(defstruct (server-identity | ||
(:constructor make-server-identity (id name))) | ||
(id nil :read-only t) | ||
(name nil :read-only t)) | ||
|
||
|
||
(defun connection-stream-of (connector) | ||
(usocket:socket-stream (connection-of connector))) | ||
|
||
|
||
(defclass connector (lockable disposable dispatcher) | ||
((enabled-p :initform t) | ||
(connection :initarg :connection :reader connection-of) | ||
(message-counter :initform 0) | ||
(message-table :initform (make-hash-table :test 'eql)))) | ||
|
||
|
||
(defmethod initialize-instance :after ((this connector) &key) | ||
(with-slots (connection message-table enabled-p) this | ||
(in-new-thread "connector-thread" | ||
(loop while enabled-p | ||
do (progn | ||
(usocket:wait-for-input connection) | ||
(let* ((message (conspack:decode-stream (connection-stream-of this))) | ||
(message-id (getf message :reply-for))) | ||
(with-instance-lock-held (this) | ||
(if-let ((handler (gethash message-id message-table))) | ||
(progn | ||
(remhash message-id message-table) | ||
(funcall handler message)) | ||
(log:error "Handler not found for message with id ~A" message-id))))) | ||
finally (usocket:socket-close connection))))) | ||
|
||
|
||
(defun connect-to-server (host &optional (port 8778)) | ||
(make-instance 'connector | ||
:connection (usocket:socket-connect host port | ||
:element-type '(unsigned-byte 8) | ||
:timeout 30))) | ||
|
||
|
||
(defun disconnect-from-server (connector) | ||
(with-slots (enabled-p) connector | ||
(setf enabled-p nil))) | ||
|
||
|
||
(defun check-response (message expected-command) | ||
(let ((command (getf message :command))) | ||
(when (eq command :error) | ||
(error "Server error of type ~A: ~A" (getf message :type) (getf message :text))) | ||
(unless (eq command expected-command) | ||
(error "Unexpected command received from server: wanted ~A, but ~A received" | ||
expected-command command)))) | ||
|
||
|
||
(defun send-command (connector &rest properties &key &allow-other-keys) | ||
(let ((stream (connection-stream-of connector))) | ||
(conspack:encode properties :stream stream) | ||
(finish-output stream))) | ||
|
||
|
||
;; (,response (conspack:decode-stream (connection-stream-of ,connector)))) | ||
(defmacro with-response (command-name (&rest properties) response &body body) | ||
`(destructuring-bind (&key ,@properties &allow-other-keys) ,response | ||
(check-response ,response ,command-name) | ||
,@body)) | ||
|
||
|
||
(defmethod dispatch ((this connector) (task function) invariant &rest keys | ||
&key &allow-other-keys) | ||
(with-slots (message-table message-counter) this | ||
(with-instance-lock-held (this) | ||
(let ((next-id (incf message-counter))) | ||
(flet ((response-callback (message) | ||
(let ((*message* message)) | ||
(funcall task)))) | ||
(setf (gethash next-id message-table) #'response-callback) | ||
(apply #'send-command this :message-id next-id keys)))))) | ||
|
||
|
||
(defun server-version (connector) | ||
(-> (connector :command :version) () | ||
(with-response :version (version) *message* | ||
version))) | ||
|
||
|
||
(defun identify (connector name) | ||
(-> (connector :command :identify :name name) () | ||
(with-response :identified (id name) *message* | ||
(make-server-identity id name)))) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters