tunnel.scm 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203
  1. ;;; tunnel.scm -- Guile-SSH tunnel tests.
  2. ;; Copyright (C) 2015, 2016 Artyom V. Poptsov <poptsov.artyom@gmail.com>
  3. ;;
  4. ;; This file is a part of Guile-SSH.
  5. ;;
  6. ;; Guile-SSH is free software: you can redistribute it and/or
  7. ;; modify it under the terms of the GNU General Public License as
  8. ;; published by the Free Software Foundation, either version 3 of the
  9. ;; License, or (at your option) any later version.
  10. ;;
  11. ;; Guile-SSH is distributed in the hope that it will be useful, but
  12. ;; WITHOUT ANY WARRANTY; without even the implied warranty of
  13. ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  14. ;; General Public License for more details.
  15. ;;
  16. ;; You should have received a copy of the GNU General Public License
  17. ;; along with Guile-SSH. If not, see <http://www.gnu.org/licenses/>.
  18. (add-to-load-path (getenv "abs_top_srcdir"))
  19. (use-modules (srfi srfi-64)
  20. (srfi srfi-26)
  21. (ice-9 rdelim)
  22. (ice-9 receive)
  23. ;; Helper procedures.
  24. (tests common)
  25. ;; Guile-SSH
  26. (ssh auth)
  27. (ssh channel)
  28. (ssh log)
  29. (ssh session)
  30. (ssh server)
  31. (ssh tunnel))
  32. (test-begin-with-log "tunnel")
  33. ;;;
  34. (define %test-string "hello scheme world")
  35. (define (call-with-connected-session/tunnel proc)
  36. (call-with-connected-session
  37. (lambda (session)
  38. (authenticate-server session)
  39. (userauth-none! session)
  40. (proc session))))
  41. (define (call-with-forward-channel session proc)
  42. (let ((channel (make-channel session)))
  43. (dynamic-wind
  44. (const #f)
  45. (lambda ()
  46. (case (channel-open-forward channel
  47. #:source-host "localhost"
  48. #:local-port (get-unused-port)
  49. #:remote-host "localhost"
  50. #:remote-port (1+ (get-unused-port)))
  51. ((ok)
  52. (proc channel))
  53. (else => (cut error "Could not open forward" <>))))
  54. (lambda () (close channel)))))
  55. (test-equal-with-log "port forwarding, direct"
  56. %test-string
  57. (run-client-test
  58. ;; server
  59. (lambda (server)
  60. (start-server/dt-test server
  61. (lambda (channel)
  62. (write-line (read-line channel) channel))))
  63. ;; client
  64. (lambda ()
  65. (call-with-connected-session/tunnel
  66. (lambda (session)
  67. (call-with-forward-channel session
  68. (lambda (channel)
  69. (write-line %test-string channel)
  70. (poll channel read-line))))))))
  71. ;; Create a tunnel, check the result.
  72. (test-assert-with-log "make-tunnel"
  73. (run-client-test
  74. ;; server
  75. (lambda (server)
  76. (start-server/dt-test server
  77. (lambda (channel)
  78. (write-line (read-line channel) channel))))
  79. (lambda ()
  80. (call-with-connected-session/tunnel
  81. (lambda (session)
  82. (let* ((local-port (get-unused-port))
  83. (remote-host "www.example.org")
  84. (tunnel (make-tunnel session
  85. #:port local-port
  86. #:host remote-host)))
  87. (and (eq? (tunnel-session tunnel) session)
  88. (string=? (tunnel-bind-address tunnel) "127.0.0.1")
  89. (eq? (tunnel-port tunnel) local-port)
  90. (eq? (tunnel-host-port tunnel) local-port)
  91. (eq? (tunnel-host tunnel) remote-host)
  92. (eq? (tunnel-reverse? tunnel) #f))))))))
  93. ;; Client calls 'call-with-ssh-forward' with a procedure which sends a string
  94. ;; to a server; server echoes the string back. Client checks if the sent
  95. ;; string and the result of 'call-with-ssh-forward' matches.
  96. ;;
  97. ;; Note that the main part of the test is done in "call/pf" process, only
  98. ;; comparison of the original string and the call result is done in the main
  99. ;; process of the test case. The reason for this is srfi-64 tests go bananas
  100. ;; when a thread is spawn in a test: the thread shares memory with the parent,
  101. ;; and it inherits the test environment, which in turn leads to errors.
  102. ;;
  103. ;; XXX: This test case contains operations that potentially can block it
  104. ;; forever.
  105. ;;
  106. ;; Here's a schematic representation of the test case:
  107. ;;
  108. ;; test
  109. ;; |
  110. ;; o Fork.
  111. ;; |___________________________________
  112. ;; o \ Fork.
  113. ;; |______________ |
  114. ;; | \ |
  115. ;; | | |
  116. ;; | | |
  117. ;; | call/pf server
  118. ;; | | |
  119. ;; | o | 'call-with-ssh-forward'
  120. ;; | |______________ |
  121. ;; | | \ |
  122. ;; | | "hello world" : |
  123. ;; | |-------------->: |
  124. ;; | | o | Re-send the message
  125. ;; | | :--->| to the server.
  126. ;; | | : o Echoing back.
  127. ;; | | :<---|
  128. ;; | | "hello world" o | Re-send the message
  129. ;; | |<--------------: | to the caller.
  130. ;; | | o | Stop the thread.
  131. ;; | o | Bind/listen a socket.
  132. ;; | "hello world" | |
  133. ;; |<--------------| |
  134. ;; o | | Check the result.
  135. ;; | | |
  136. ;;
  137. (test-equal-with-log "call-with-ssh-forward"
  138. %test-string
  139. (run-client-test/separate-process
  140. ;; Server
  141. (lambda (server)
  142. (start-server/dt-test server
  143. (lambda (channel)
  144. (poll channel
  145. (lambda (channel)
  146. (write-line (read-line channel) channel))))))
  147. ;; Client (call/pf)
  148. (lambda ()
  149. (set-log-userdata! (string-append (get-log-userdata) " (call/pf)"))
  150. (call-with-connected-session/tunnel
  151. (lambda (session)
  152. (let* ((local-port (get-unused-port))
  153. (remote-host "www.example.org")
  154. (tunnel (make-tunnel session
  155. #:port local-port
  156. #:host remote-host)))
  157. (call-with-ssh-forward tunnel
  158. (lambda (sock)
  159. (write-line %test-string sock)
  160. (poll sock read-line)))))))
  161. ;; Handle the result.
  162. (lambda (result)
  163. result)))
  164. (test-assert-with-log "channel-{listen,cancel}-forward"
  165. (run-client-test
  166. ;; Server
  167. (lambda (server)
  168. (start-server/dist-test server))
  169. ;; Client
  170. (lambda ()
  171. (call-with-connected-session/tunnel
  172. (lambda (session)
  173. (let ((portnum (get-unused-port)))
  174. (and
  175. (receive (result pnum)
  176. (channel-listen-forward session
  177. #:address "localhost"
  178. #:port portnum)
  179. (and (equal? result 'ok)
  180. (= pnum portnum)))
  181. (eq? (channel-cancel-forward session "localhost" portnum) 'ok))))))))
  182. (test-end "tunnel")
  183. (exit (= (test-runner-fail-count (test-runner-current)) 0))
  184. ;;; tunnel.scm ends here.