Handle incrementing transaction id

This commit is contained in:
Jakub 2026-05-09 13:21:38 +08:00
parent e8f20ab828
commit 4d0d2a0f8a
2 changed files with 67 additions and 53 deletions

View file

@ -41,6 +41,8 @@
(cl-defstruct gomuks-session (cl-defstruct gomuks-session
user token transaction-id user token transaction-id
websocket
ping-timer
;; Hash table of available rooms ;; Hash table of available rooms
rooms) rooms)

118
gomuks.el
View file

@ -36,14 +36,12 @@
(defvar client-state (make-gomuks-state :rooms '() :spaces '())) (defvar client-state (make-gomuks-state :rooms '() :spaces '()))
(defvar gomuks-current-session nil)
(defvar gomuks-server-buffer "*gomuks-server*") (defvar gomuks-server-buffer "*gomuks-server*")
(defvar gomuks-socket-buffer "*gomuks-socket-frame*") (defvar gomuks-socket-buffer "*gomuks-socket-frame*")
(defvar gomuks-server-name "*gomuks-server*") (defvar gomuks-server-name "*gomuks-server*")
(defvar gomuks-auth-cookie nil)
(defvar gomuks-websocket nil)
(defvar gomuks-ping-timer nil)
(defcustom gomuks-server-binary "~/tmp/gomuks" (defcustom gomuks-server-binary "~/tmp/gomuks"
"The Gomuks backend binary." "The Gomuks backend binary."
:type 'string :type 'string
@ -69,61 +67,61 @@
(notifications-notify :title "Gomuks Server Closed" :app-name "gomuks.el")) (notifications-notify :title "Gomuks Server Closed" :app-name "gomuks.el"))
(defvar gomuks-auth-endpoint (concat "http://" gomuks-base-url "/_gomuks/auth")) (defvar gomuks-auth-endpoint (concat "http://" gomuks-base-url "/_gomuks/auth"))
(defvar gomuks-auth-cookie)
(defvar gomuks-ws-endpoint (concat "ws://" gomuks-base-url "/_gomuks/websocket")) (defvar gomuks-ws-endpoint (concat "ws://" gomuks-base-url "/_gomuks/websocket"))
(defun gomuks-connect (gomuks-username) (defun gomuks-connect (gomuks-username)
"Opens a websocket connection with the specified gomuks endpoint" "Opens a websocket connection with the specified gomuks endpoint"
(interactive "sGomuks Username: \n") (interactive "sGomuks Username: \n")
(let ((gomuks-password (read-passwd "Gomuks Password: "))) (let ((gomuks-password (read-passwd "Gomuks Password: "))
(setq gomuks-auth-cookie (let ((request--curl-cookie-jar (expand-file-name (make-temp-name "gomuks-cookie-") (gomuks-auth-cookie (let ((request--curl-cookie-jar (expand-file-name (make-temp-name "gomuks-cookie-")
temporary-file-directory))) temporary-file-directory)))
(request gomuks-auth-endpoint (request gomuks-auth-endpoint
:type "POST" :type "POST"
:headers `(("Authorization" . :headers `(("Authorization" .
,(concat "Basic " ,(concat "Basic "
(base64-encode-string (base64-encode-string
(concat gomuks-username ":" gomuks-password)))))) (concat gomuks-username ":" gomuks-password))))))
(sleep-for 0.5) (sleep-for 0.5)
;; TODO: this needs to select domain dynamically, instead of hardcoding a string here ;; TODO: this needs to select domain dynamically, instead of hardcoding a string here
(cdar (request--netscape-get-cookies request--curl-cookie-jar "localhost" "/_gomuks" t))))) (cdar (request--netscape-get-cookies request--curl-cookie-jar "localhost" "/_gomuks" t)))))
(setq gomuks-ping-timer (run-with-timer (setq gomuks-current-session
0 (make-gomuks-session :token gomuks-auth-cookie :transaction-id 0
15 :ping-timer (run-with-timer
(lambda () 0
(message "pinging") 15
(websocket-send-text gomuks-websocket (lambda ()
"{\"command\":\"ping\"}")))) (gomuks-send-message "ping")))
(setq gomuks-websocket (websocket-open gomuks-ws-endpoint :websocket (websocket-open
:custom-header-alist gomuks-ws-endpoint
`(("Cookie" . ,(concat "gomuks_auth=" gomuks-auth-cookie))) :custom-header-alist
:on-message (lambda (_ws frame) `(("Cookie" . ,(concat "gomuks_auth=" gomuks-auth-cookie)))
(message "frame %s %s" (websocket-frame-completep frame) (websocket-frame-text :on-message (lambda (_ws frame)
frame)) (message "frame %s %s" (websocket-frame-completep frame) (websocket-frame-text
(cond frame))
((not (websocket-frame-completep frame)) (cond
(message "frame incomplete") ((not (websocket-frame-completep frame))
(with-current-buffer (get-buffer-create gomuks-socket-buffer) (message "frame incomplete")
(goto-char (point-max)) (with-current-buffer (get-buffer-create gomuks-socket-buffer)
(insert (websocket-frame-payload frame)))) (goto-char (point-max))
(t (insert (websocket-frame-payload frame))))
(message "frame complete") (t
(let* ((combined-payload (message "frame complete")
(unwind-protect (let* ((combined-payload
(with-current-buffer (get-buffer-create gomuks-socket-buffer) (unwind-protect
(goto-char (point-max)) (with-current-buffer (get-buffer-create gomuks-socket-buffer)
(insert (websocket-frame-payload frame)) (goto-char (point-max))
(message "%s" (buffer-string)) (insert (websocket-frame-payload frame))
(buffer-string)) (message "%s" (buffer-string))
(kill-buffer (get-buffer-create gomuks-socket-buffer)))) (buffer-string))
(msg (json-parse-string (decode-coding-string combined-payload 'utf-8) (kill-buffer (get-buffer-create gomuks-socket-buffer))))
:object-type 'alist (msg (json-parse-string (decode-coding-string combined-payload 'utf-8)
:array-type 'list :object-type 'alist
:null-object '()))) :array-type 'list
(message "test %S" msg) :null-object '())))
(cond ((equal (alist-get 'command msg) "sync_complete") (message "test %S" msg)
(gomuks-sync-state (alist-get 'data msg))))))))))) (cond ((equal (alist-get 'command msg) "sync_complete")
(gomuks-sync-state (alist-get 'data msg)))))))))))))
(defun gomuks-disconnect () (defun gomuks-disconnect ()
"Disconnect the gomuks websocket." "Disconnect the gomuks websocket."
@ -131,6 +129,20 @@
(cancel-timer gomuks-ping-timer) (cancel-timer gomuks-ping-timer)
(websocket-close gomuks-websocket)) (websocket-close gomuks-websocket))
(defun gomuks-send-message (command &optional data)
"Send a message down the gomuks websocket, automatically incrementing the session transaction ID.
`command' is the command string to send, and `data' is an alist that is converted to JSON as required by the command."
(setf (gomuks-session-transaction-id gomuks-current-session) (+ 1 (gomuks-session-transaction-id gomuks-current-session)))
(websocket-send-text
(gomuks-session-websocket gomuks-current-session)
(json-serialize
(let ((command-header `((command . ,command)
(request_id . ,(gomuks-session-transaction-id gomuks-current-session)))))
(if data
(append command-header
`((data . ,data)))
command-header)))))
(defun gomuks-process-initial-events (events) (defun gomuks-process-initial-events (events)
(mapcar (mapcar
(lambda (event) (lambda (event)