|
6 | 6 | [clj-libssh2.libssh2.session :as libssh2-session])
|
7 | 7 | (:import [com.sun.jna.ptr IntByReference PointerByReference]))
|
8 | 8 |
|
9 |
| -(def timeouts |
10 |
| - "An atom map where the keys are keywords being the symbolic names of named |
11 |
| - timeouts (see get-timeout/set-timeout) and the values are the number of |
12 |
| - milliseconds for that timeout." |
13 |
| - (atom {:agent 10000 |
14 |
| - :auth 10000 |
15 |
| - :known-hosts 10000})) |
16 |
| - |
17 | 9 | (def error-messages
|
18 | 10 | "All of the error codes that are documented for libssh2 except for
|
19 | 11 | LIBSSH2_ERROR_SOCKET_NONE which despite its name is a generic error and
|
|
172 | 164 | (maybe-throw-error (:session session#) res#)
|
173 | 165 | res#))
|
174 | 166 |
|
175 |
| -(defn get-timeout |
176 |
| - "Get a timeout value. |
| 167 | +(defn enforce-timeout |
| 168 | + "Throw an error if a timeout has been exceeded. |
177 | 169 |
|
178 | 170 | Arguments:
|
179 | 171 |
|
180 |
| - name-or-value Either the name of a symbolic timeout (e.g. :session) or a |
181 |
| - number of milliseconds. |
182 |
| -
|
183 |
| - Return: |
184 |
| -
|
185 |
| - A number of milliseconds for the timeout." |
186 |
| - [name-or-value] |
187 |
| - (or (get @timeouts name-or-value) name-or-value 1000)) |
188 |
| - |
189 |
| -(defn set-timeout |
190 |
| - "Update a timeout value. |
191 |
| -
|
192 |
| - Arguments: |
193 |
| -
|
194 |
| - timeout-name The name of a symbolic timeout. |
195 |
| - millis The number of milliseconds for that timeout. |
196 |
| -
|
197 |
| - Return: |
198 |
| -
|
199 |
| - A map of all the current symbolic timeouts." |
200 |
| - [timeout-name millis] |
201 |
| - (swap! timeouts assoc timeout-name millis)) |
| 172 | + session The clj-libssh2.session.Session object for the current session. |
| 173 | + start-time The time the timeout is relative to. |
| 174 | + timeout The number of milliseconds describing the timeout value." |
| 175 | + [session start-time timeout] |
| 176 | + (when (< (if (keyword? timeout) |
| 177 | + (-> session :options :timeout timeout) |
| 178 | + timeout) |
| 179 | + (- (System/currentTimeMillis) start-time)) |
| 180 | + (handle-errors session libssh2/ERROR_TIMEOUT))) |
202 | 181 |
|
203 | 182 | (defmacro with-timeout
|
204 | 183 | "Run some code that could return libssh2/ERROR_EAGAIN and if it does, retry
|
|
213 | 192 |
|
214 | 193 | Arguments:
|
215 | 194 |
|
216 |
| - timeout Either a number of milliseconds or a keyword referring to a named |
217 |
| - timeout set using set-timeout. |
| 195 | + session The clj-libssh2.session.Session object for the current session. |
| 196 | + timeout A number of milliseconds specifying the timeout. This macro will |
| 197 | + wait for at least that number of milliseconds before failing with a |
| 198 | + timeout error. It may return successfully sooner, but this value is |
| 199 | + the minimum time you will wait for failure. The argument can also be |
| 200 | + passed a keyword which will be looked up in the :timeout section of |
| 201 | + the session options. |
218 | 202 |
|
219 | 203 | Return:
|
220 | 204 |
|
221 | 205 | Either the return value of the code being wrapped or an exception if the
|
222 | 206 | timeout is exceeded."
|
223 |
| - [timeout & body] |
| 207 | + [session timeout & body] |
224 | 208 | `(let [start# (System/currentTimeMillis)
|
225 |
| - timeout# (get-timeout ~timeout)] |
226 |
| - (loop [timedout# false] |
227 |
| - (if timedout# |
228 |
| - (raise (format "Timeout of %d ms exceeded" timeout#) |
229 |
| - {:timeout ~timeout |
230 |
| - :timeout-length timeout#}) |
231 |
| - (let [r# (do ~@body)] |
232 |
| - (if (= r# libssh2/ERROR_EAGAIN) |
233 |
| - (recur (< timeout# (- (System/currentTimeMillis) start#))) |
234 |
| - r#)))))) |
| 209 | + session# ~session |
| 210 | + timeout# ~timeout] |
| 211 | + (loop [result# (do ~@body)] |
| 212 | + (enforce-timeout session# start# timeout#) |
| 213 | + (if (= result# libssh2/ERROR_EAGAIN) |
| 214 | + (recur (do ~@body)) |
| 215 | + result#)))) |
0 commit comments