-
Notifications
You must be signed in to change notification settings - Fork 2
/
conditions.lisp
118 lines (94 loc) · 4.78 KB
/
conditions.lisp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
(defpackage #:conditions
(:use #:CL)
(:export #:*ERRORS*
#:*ERROR-MAP*
#:get-conditions)) ;; other conditions symbol export in macro `auto-make-conditions`
(in-package #:conditions)
;;; Macro will expand first and run in toplevel, and macro need
;;; *ERRORS* and *ERROR-MAP*, so these two global var should run in
;;; compilation time
(eval-when (:compile-toplevel :load-toplevel :execute)
(defvar *ERRORS*
'((unknown-protocol
("'Unknown Protocol Operation'" . ;; this is err-msg in `get-conditions`
"Unknown protocol error"))
(connent-to-route-port
("'Attempted To Connect To Route Port'" .
"Client attempted to connect to a route port instead of the client port"))
(authorization-violation
("'Authorization Violation'" .
"Client failed to authenticate to the server with credentials specified in the CONNECT message"))
(authorization-timeout
("'Authorization Timeout'" .
"Client took too long to authenticate to the server after establishing a connection (default 1 second)"))
(invalid-client-protocol
("'Invalid Client Protocol'" .
"Client specified an invalid protocol version in the CONNECT message"))
(maximum-control-line-exceeded
("'Maximum Control Line Exceeded'" .
"Message destination subject and reply subject length exceeded the maximum control line value specified by the max_control_line server option. The default is 1024 bytes."))
(parser-error
("'Parser Error'" .
"Cannot parse the protocol message sent by the client"))
(TLS-required
("'Secure Connection - TLS Required'" .
"The server requires TLS and the client does not have TLS enabled."))
(stale-connection
("'Stale Connection'" .
"The server hasn't received a message from the client, including a PONG in too long."))
(maximum-connections-exceeded
("'Maximum Connections Exceeded'" .
"This error is sent by the server when creating a new connection and the server has exceeded the maximum number of connections specified by the max_connections server option. The default is 64k."))
(slow-consumer
("'Slow Consumer'" .
"The server pending data size for the connection has reached the maximum size (default 10MB)."))
(maximum-payload-violation
("'Maximum Payload Violation'" .
"Client attempted to publish a message with a payload size that exceeds the max_payload size configured on the server. This value is supplied to the client upon connection in the initial INFO message. The client is expected to do proper accounting of byte size to be sent to the server in order to handle this error synchronously."))
(invalid-subject
("'Invalid Subject'" .
"Client sent a malformed subject (e.g. sub foo. 90)"))
(permissions-violation-for-sub
("'Permissions Violation for Subscription to <subject>'" .
"The user specified in the CONNECT message does not have permission to subscribe to the subject."))
(permissions-violation-for-pub
("'Permissions Violation for Publish to <subject>'" .
"The user specified in the CONNECT message does not have permissions to publish to the subject."))
;; for all other errors unknown
(unknown-error
("Unknown Error" .
"Something wrong"))
))
(defvar *ERROR-MAP* (make-hash-table :test #'equal)))
(defmacro auto-make-conditions ()
(loop
for e in *errors*
collect (let ((symbol (car e))
(msg (caadr e))
(detail (cdadr e)))
(setf (gethash msg *ERROR-MAP*) symbol) ;; insert condition in *error-map*
(export symbol)
`(define-condition ,symbol (error)
((error-message
:initarg :error-message
:initform ,msg))
(:documentation ,detail)))
into result
finally (return (cons 'progn result))
))
(defun get-conditions (err-msg)
"receive err-msg and return the condition in *ERROR-MAP*"
(let ((result (gethash err-msg *ERROR-MAP*)))
(if result
result
(let* ((last-space-postion (position #\space err-msg :from-end t))
(head-msg (subseq err-msg 0 last-space-postion)))
(cond ((string= "Permissions Violation for Subscription to"
head-msg)
'permissions-violation-for-sub)
((string= "Permissions Violation for Publish to"
head-msg)
'permissions-violation-for-pub)
(t 'unknown-error))))))
;;; expand macro in toplevel, auto make all conditions.
(auto-make-conditions)