Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Moved out EPMD client code into new file epmd-client.lisp to prepare …
…for refactoring.
- Loading branch information
Showing
3 changed files
with
121 additions
and
118 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
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,117 @@ | ||
;;;; Functions for querying EPMD (Erlang Port Mapped Daemon) | ||
|
||
(in-package :cleric-epmd) | ||
|
||
;;; EPMD port | ||
(defconstant +epmd-port+ 4369 | ||
"The default TCP port the EPMD listens on.") | ||
|
||
(defvar *epmd-socket* nil | ||
"The EPMD socket. NIL if not registered in EPMD.") | ||
|
||
|
||
|
||
(defun connect-to-epmd (&optional (host "localhost")) | ||
(let ((socket (handler-case (usocket:socket-connect host | ||
+epmd-port+ | ||
:element-type 'octet) | ||
(usocket:connection-refused-error () | ||
(error 'unreachable-error)) | ||
(usocket:unknown-error () | ||
(error 'host-unknown-error))))) | ||
(setf (usocket:socket-stream socket) | ||
(make-flexi-stream (usocket:socket-stream socket))) | ||
socket)) | ||
|
||
|
||
;;; | ||
;;; WITH-EPMD-CONNECTION-STREAM macro | ||
;;; | ||
|
||
(defmacro with-epmd-connection-stream | ||
((stream-var &optional (host "localhost")) &body body) | ||
"Create a local scope where STREAM-VAR is a socket stream connected to the EPMD." | ||
(let ((socket-var (gensym))) | ||
`(let* ((,socket-var (connect-to-epmd ,host)) | ||
(,stream-var (usocket:socket-stream ,socket-var))) | ||
(unwind-protect (progn ,@body) | ||
(usocket:socket-close ,socket-var))) )) | ||
|
||
|
||
;;; | ||
;;; EPMD API | ||
;;; | ||
|
||
(defun publish () | ||
(if *epmd-socket* | ||
(error 'already-registered) | ||
(restart-case | ||
(if (not (listening-p)) | ||
(error 'not-listening-on-socket) | ||
(let* ((socket (connect-to-epmd)) | ||
(epmd (usocket:socket-stream socket))) | ||
(write-alive2-request | ||
epmd (node-name (this-node)) (listening-port)) | ||
(finish-output epmd) | ||
(let ((creation (read-alive2-response epmd))) | ||
(declare (ignore creation)) | ||
(setf *epmd-socket* socket) | ||
t))) | ||
(start-listening-on-socket () | ||
:report "Start listening on a socket." | ||
:test (lambda (c) | ||
(declare (ignore c)) | ||
(not (listening-p))) | ||
(start-listening) | ||
(publish))))) | ||
|
||
(defun published-p () | ||
(not (null *epmd-socket*))) | ||
|
||
(defun unpublish () | ||
(when *epmd-socket* | ||
(usocket:socket-close *epmd-socket*) | ||
(setf *epmd-socket* nil) | ||
t)) | ||
|
||
(defun lookup-node (node-name &optional (host "localhost")) | ||
"Query the EPMD about a node. Returns a REMOTE-NODE object that represents the node." | ||
(with-epmd-connection-stream (epmd host) | ||
(write-port-please2-request epmd node-name) | ||
(finish-output epmd) | ||
(read-port-please2-response epmd host))) | ||
|
||
(defun print-all-registered-nodes (&optional (host "localhost") (stream t)) | ||
"Query the EPMD about all registered nodes and print the information." | ||
(with-epmd-connection-stream (epmd host) | ||
(write-names-request epmd) | ||
(finish-output epmd) | ||
(multiple-value-bind (epmd-port node-info) | ||
(read-names-response epmd) | ||
(declare (ignore epmd-port)) | ||
(format stream "~{~a~%~}" node-info) | ||
t))) | ||
|
||
|
||
;;; | ||
;;; Conditions | ||
;;; | ||
|
||
(define-condition already-registered (error) | ||
() | ||
(:documentation "This error is signaled when trying to register on the EPMD when already registered.")) | ||
|
||
(define-condition host-unknown-error (error) | ||
;; USOCKET:UNKNOWN-ERROR | ||
() | ||
(:documentation "This error is signaled if the hostname for EPMD is unresolvable.")) | ||
|
||
(define-condition unreachable-error (error) | ||
;; USOCKET:CONNECTION-REFUSED-ERROR | ||
() | ||
(:documentation "This error is signaled when the EPMD is unreachable.")) | ||
|
||
(define-condition response-error (error) | ||
;; Useful? | ||
() | ||
(:documentation "This error is signaled when the EPMD sends an error response.")) |
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