branch: externals/crdt commit 38fdfc55575f906fcf1f0a8eb9180bce2cd79d17 Author: Qiantan Hong <qh...@mit.edu> Commit: Qiantan Hong <qh...@mit.edu>
semver, and various fixes --- HACKING.org | 2 +- crdt.el | 50 +++++++++++++++++++++++++++++++++++++------------- 2 files changed, 38 insertions(+), 14 deletions(-) diff --git a/HACKING.org b/HACKING.org index 9bcd78a39f..af7c2031dc 100644 --- a/HACKING.org +++ b/HACKING.org @@ -56,7 +56,7 @@ and second last two bytes represent site ID. - Login + hello :: This message is sent from client to server, when a client connect to the server. - body takes the form =(client-name &optional response)= + body takes the form =(client-name protocol-version &optional response)= + leave :: This message is sometime sent from client to server to indicate disconnection, diff --git a/crdt.el b/crdt.el index 3c27c1ad2a..9878786a71 100644 --- a/crdt.el +++ b/crdt.el @@ -35,6 +35,14 @@ (require 'url) (require 'color) +(defconst crdt-version "0.2.5") +(defconst crdt-protocol-version "0.2.5") + +(defun crdt-version () + "Show the crdt.el version." + (interactive) + (message crdt-version)) + (defgroup crdt nil "Collaborative editing using Conflict-free Replicated Data Types." :prefix "crdt-" @@ -111,8 +119,7 @@ "Move pseudo marked region overlay OV to mark between POS and MARK." (move-overlay ov (min pos mark) (max pos mark))) - -;; CRDT ID utils +;;; CRDT ID utils ;; CRDT IDs are represented by unibyte strings (for efficient comparison) ;; Every two bytes represent a big endian encoded integer ;; For base IDs, last two bytes are always representing site ID @@ -1591,9 +1598,19 @@ CRDT--PROCESS should be bound to The network process for the client connection." (define-crdt-message-handler error (buffer-name &rest err) (unless (crdt--server-p) - (crdt--with-buffer-name buffer-name - (message "Server side error %s." err) - (crdt--recover)))) + (if buffer-name + (crdt--with-buffer-name buffer-name + (message "Server side error %s." err) + (crdt--recover)) + (cl-block nil + (message "Server side error %s." err) + (when (eq (car err) 'version) + (if (version< crdt-protocol-version (cadr err)) + (warn "Server uses newer crdt.el protocol (%s>%s). Please update your crdt.el to connect." + (cadr err) crdt-protocol-version) + (warn "Server uses older crdt.el protocol (%s<%s). Please ask to update server." + (cadr err) crdt-protocol-version))) + (crdt-disconnect))))) (define-crdt-message-handler add (&rest buffer-names) (dolist (buffer-name buffer-names) @@ -1645,7 +1662,7 @@ CRDT--PROCESS should be bound to The network process for the client connection." (process-contact (crdt--session-network-process crdt--session) :host) (process-contact (crdt--session-network-process crdt--session) :service))))) (crdt--broadcast-maybe (crdt--format-message - `(hello ,(crdt--session-local-name crdt--session) + `(hello ,(crdt--session-local-name crdt--session) ,crdt-protocol-version ,(gnutls-hash-mac 'SHA1 password hash))))))) (define-crdt-message-handler contact (site-id display-name &optional host service) @@ -1707,7 +1724,11 @@ Handle received STRING from PROCESS." (crdt-process-message message string)) (cl-block nil (when (eq (car message) 'hello) - (cl-destructuring-bind (name &optional response) (cdr message) + (cl-destructuring-bind (name protocol-version &optional response) (cdr message) + (when (version< protocol-version crdt-protocol-version) + (process-send-string process + (crdt--format-message `(error nil version ,crdt-protocol-version))) + (cl-return)) (when (or (not (process-get process 'password)) ; server password is empty (and response (string-equal response (process-get process 'challenge)))) (process-put process 'authenticated t) @@ -1719,7 +1740,7 @@ Handle received STRING from PROCESS." (gnutls-hash-mac 'SHA1 (substring (process-get process 'password)) challenge)) (process-send-string process (crdt--format-message `(challenge ,challenge)))))) ((crdt-unrecognized-message invalid-read-syntax) - (message "%s error when processing message %s from %s:%s, disconnecting." err message + (warn "%s error when processing message %s from %s:%s, disconnecting." err message (process-contact process :host) (process-contact process :service)) (if (crdt--server-p) (delete-process process) @@ -1911,14 +1932,15 @@ Setup up the server with PASSWORD and assign this Emacs DISPLAY-NAME." (kill-buffer process-buffer)) (when (and proxy-process (process-live-p proxy-process)) (interrupt-process proxy-process))) - (warn "CRDT session disconnected."))) + (unless (memq last-command '(crdt-disconnect crdt-stop-session)) + (warn "CRDT session %s disconnected." (crdt--session-name session))))) (defun crdt-stop-session (&optional session) "Stop sharing the SESSION. If SESSION is nil, stop sharing the current session." (interactive (list (crdt--read-session-maybe 'server))) - (crdt--stop-session session)) + (crdt--stop-session (or session crdt--session))) (defun crdt-copy-url (&optional session-name) "Copy the url for the session with SESSION-NAME. @@ -1952,7 +1974,7 @@ Currently this only work if a tuntox proxy is used." If SESSION is nil, disconnect from the current session." (interactive (list (crdt--read-session-maybe 'client))) - (crdt--stop-session session)) + (crdt--stop-session (or session crdt--session))) (defvar crdt-connect-url-history nil) @@ -1997,8 +2019,10 @@ Join with DISPLAY-NAME." (process-put network-process 'crdt-session new-session) (push new-session crdt--session-list) ,@body - (process-send-string network-process - (crdt--format-message `(hello ,(crdt--session-local-name new-session)))) + (process-send-string + network-process + (crdt--format-message + `(hello ,(crdt--session-local-name new-session) ,crdt-protocol-version))) (let ((crdt--session new-session)) (crdt-list-buffers))))) (cond ((equal url-type "tcp")