Skip to content

Commit 7a9f460

Browse files
committed
Merge branch 'no-session-pooling'
2 parents 181be43 + 9d5f8ab commit 7a9f460

File tree

4 files changed

+35
-73
lines changed

4 files changed

+35
-73
lines changed

src/clj_libssh2/session.clj

Lines changed: 30 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,18 @@
11
(ns clj-libssh2.session
22
"Functions for creating and managing sessions."
3-
(:require [clj-libssh2.libssh2 :as libssh2]
3+
(:require [clojure.set :as set]
4+
[clj-libssh2.libssh2 :as libssh2]
45
[clj-libssh2.libssh2.session :as libssh2-session]
56
[clj-libssh2.authentication :refer [authenticate]]
67
[clj-libssh2.error :refer [handle-errors with-timeout]]
78
[clj-libssh2.known-hosts :as known-hosts]
89
[clj-libssh2.socket :as socket]))
910

1011
(def sessions
11-
"A pool of currently running sessions. This is an atomic map where the keys
12-
are session IDs and the values are running session objects."
13-
(atom {}))
12+
"An atomic set of currently active sessions. This is used to trigger calls to
13+
libssh2/init and libssh2/exit at appropriate times. It's also used to
14+
protect against attempting to close sessions twice."
15+
(atom #{}))
1416

1517
(def default-opts
1618
"The default options for a session. These are not only the defaults, but an
@@ -23,7 +25,7 @@
2325
:read-timeout 60000
2426
:write-chunk-size (* 1024 1024)})
2527

26-
(defrecord Session [id session socket host port options])
28+
(defrecord Session [session socket host port options])
2729

2830
(defn- create-session
2931
"Make a native libssh2 session object.
@@ -96,27 +98,6 @@
9698
(with-timeout :session
9799
(libssh2-session/handshake session socket))))
98100

99-
(defn- session-id
100-
"Generate the session ID that will be used to pool sessions.
101-
102-
Arguments:
103-
104-
host The hostname or IP of the remote host.
105-
port The port we're connecting to.
106-
credentials The credentials to be used to authenticate the session.
107-
opts The session options.
108-
109-
Return:
110-
111-
A string that will uniquely identify a session."
112-
[host port credentials opts]
113-
(format "%s@%s:%d-%d-%d"
114-
(:username credentials)
115-
host
116-
port
117-
(.hashCode credentials)
118-
(.hashCode opts)))
119-
120101
(defn close
121102
"Disconnect an SSH session and discard the session.
122103
@@ -127,11 +108,11 @@
127108
Return:
128109
129110
nil."
130-
[{id :id}]
131-
(when-let [session (get @sessions id)]
111+
[session]
112+
(when (contains? @sessions session)
132113
(destroy-session session)
133114
(socket/close (:socket session))
134-
(swap! sessions dissoc id)
115+
(swap! sessions set/difference #{session})
135116
(when (empty? @sessions)
136117
(libssh2/exit))))
137118

@@ -149,33 +130,26 @@
149130
Return:
150131
151132
A Session object for the connected and authenticated session."
152-
([host port credentials]
153-
(open host port credentials {}))
154-
([host port credentials opts]
155-
(when (empty? @sessions)
156-
(handle-errors nil (libssh2/init 0)))
157-
(let [session-options (create-session-options opts)
158-
id (session-id host port credentials session-options)]
159-
(if (contains? @sessions id)
160-
(get @sessions id)
161-
(let [session (Session. id
162-
(create-session)
163-
(socket/connect host port)
164-
host
165-
port
166-
session-options)]
167-
(when (> 0 (:socket session))
168-
(destroy-session session "Shutting down due to bad socket." true))
169-
(try
170-
(libssh2-session/set-blocking (:session session) 0)
171-
(handshake session)
172-
(known-hosts/check session)
173-
(authenticate session credentials)
174-
(swap! sessions assoc (:id session) session)
175-
(get @sessions (:id session))
176-
(catch Exception e
177-
(close session)
178-
(throw e))))))))
133+
[host port credentials opts]
134+
(when (empty? @sessions)
135+
(handle-errors nil (libssh2/init 0)))
136+
(let [session (Session. (create-session)
137+
(socket/connect host port)
138+
host
139+
port
140+
(create-session-options opts))]
141+
(when (> 0 (:socket session))
142+
(destroy-session session "Shutting down due to bad socket." true))
143+
(try
144+
(libssh2-session/set-blocking (:session session) 0)
145+
(handshake session)
146+
(known-hosts/check session)
147+
(authenticate session credentials)
148+
(swap! sessions conj session)
149+
session
150+
(catch Exception e
151+
(close session)
152+
(throw e)))))
179153

180154
(defmacro with-session
181155
"A convenience macro for running some code with a particular session.

test/clj_libssh2/test_agent.clj

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,7 @@
99

1010
(defn agent-session
1111
[]
12-
(session/open test/ssh-host
13-
test/ssh-port
14-
{:username (test/ssh-user)}))
12+
(session/open test/ssh-host test/ssh-port {:username (test/ssh-user)} {}))
1513

1614
(defn open-and-close
1715
[]

test/clj_libssh2/test_authentication.clj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
(defn auth
1212
[creds]
1313
(is (= 0 (count @session/sessions)))
14-
(let [session (session/open test/ssh-host test/ssh-port creds)]
14+
(let [session (session/open test/ssh-host test/ssh-port creds {})]
1515
(is (= 1 (count @session/sessions)))
1616
(session/close session))
1717
(is (= 0 (count @session/sessions))))

test/clj_libssh2/test_session.clj

Lines changed: 3 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,8 @@
1212
(session/open test/ssh-host
1313
test/ssh-port
1414
(merge {:username (test/ssh-user)}
15-
(apply hash-map creds))))
15+
(apply hash-map creds))
16+
{}))
1617

1718
(deftest close-is-robust
1819
(testing "Closing a good, open connection does not fail."
@@ -31,16 +32,6 @@
3132
(session/close nil)))
3233

3334
(deftest open-works
34-
(testing "sessions are pooled"
35-
(is (= 0 (count @session/sessions)))
36-
(let [session1 (open)]
37-
(is (= 1 (count @session/sessions)))
38-
(let [session2 (open)]
39-
(is (= 1 (count @session/sessions)))
40-
(is (= session1 session2))
41-
(session/close session1)
42-
(session/close session2)
43-
(is (= 0 (count @session/sessions))))))
4435
(testing "throws but doesn't crash on handshake failure"
4536
(with-redefs [libssh2-session/handshake (constantly libssh2/ERROR_PROTO)]
4637
(is (= 0 (count @session/sessions)))
@@ -56,5 +47,4 @@
5647
test/ssh-port
5748
{:username (test/ssh-user)}
5849
{:bad-option :bad-option-value})))
59-
(is (= 0 (count @session/sessions)))
60-
))
50+
(is (= 0 (count @session/sessions)))))

0 commit comments

Comments
 (0)