Created
December 3, 2015 21:25
-
-
Save artyom-poptsov/bb25d5a7518e889f0ccb to your computer and use it in GitHub Desktop.
Forwarding of data to a remote Unix socket using 'with-ssh' from (ssh dist) module.
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
#!/usr/bin/guile \ | |
-e main -s | |
!# | |
;;; forwarding-to-unix-socket.scm | |
;; Copyright (C) 2015 Artyom V. Poptsov <poptsov.artyom@gmail.com> | |
;; | |
;; This program is free software: you can redistribute it and/or | |
;; modify it under the terms of the GNU General Public License as | |
;; published by the Free Software Foundation, either version 3 of the | |
;; License, or (at your option) any later version. | |
;; | |
;; This program is distributed in the hope that it will be useful, but | |
;; WITHOUT ANY WARRANTY; without even the implied warranty of | |
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
;; General Public License for more details. | |
;; | |
;; You should have received a copy of the GNU General Public License | |
;; along with this program. If not, see <http://www.gnu.org/licenses/>. | |
;;; Commentary: | |
;; The program uses 'with-ssh' to start a remote process that forwards | |
;; data to a Unix socket. This is aimed to model a situation when | |
;; it's needed to communicate with a remote application that listens | |
;; to a Unix socket. | |
;; | |
;; *Note* that "remote" REPL servers will be started automatically; | |
;; they won't be stopped when the program stops. | |
;; | |
;; The program is known to work on the Guile-SSH 'master' branch, | |
;; commit '1673d06'. | |
;; | |
;; Here's the diagram that shows how it should work: | |
;; | |
;; This program Guile REPL Guile REPL | |
;; server 1 server 2 | |
;; (port: 37147) (port: 37148) | |
;; ................ .............. .................... | |
;; : "Hello" : : : : : | |
;; : | : : : : : | |
;; : V : : : : : | |
;; : [local-0] : : : : [/tmp/hello.txt] : | |
;; : | : : : : A : | |
;; : V : : : : | : | |
;; : [local-1] : : [local-2] : : [local-3] : | |
;; : | : : A | : : A : | |
;; : | SSH tunnel | | Unix socket | : | |
;; : ` `----------------'` `-----------------' : | |
;; : : : : : : | |
;; '..............: :............: :..................: | |
;; | |
;; As can be seen above, there are 4 processes named [local-0], | |
;; [local-1], [local-2], [local-3]. | |
;; | |
;; [local-0] is the main thread of this application. [local-1] is a | |
;; thread will be spawned by the application in order to transfer data | |
;; through an SSH tunnel. | |
;; | |
;; [local-2] will run in the 1st REPL server and will listen to | |
;; incoming connection on a local TCP socket. | |
;; | |
;; [local-3] will listen to a local Unix socket and in therefore | |
;; imitate a remote application (for example, GuixSD.) | |
;;; Code: | |
(use-modules (ice-9 rdelim) | |
;; Guile-SSH | |
(ssh session) | |
(ssh auth) | |
(ssh dist) | |
(ssh tunnel)) | |
(define %tunnel-port-number 12400) | |
;; [local-3] | |
;; | |
;; This process will listen a Unix socket. | |
(define (start-local-3) | |
(display "Starting [local-3] ... ") | |
(let ((thread | |
(call-with-new-thread | |
(lambda () | |
(let ((session (make-session #:host "localhost"))) | |
(connect! session) | |
(authenticate-server session) | |
(userauth-agent! session) | |
(with-ssh (make-node session 37148) | |
(use-modules (ice-9 rdelim)) | |
(let ((sock (socket PF_UNIX SOCK_STREAM 0))) | |
(setsockopt sock SOL_SOCKET SO_REUSEADDR 1) | |
;; Bind the Unix socket and listen it. | |
(bind sock AF_UNIX "/tmp/start-remote-process") | |
(listen sock 5) | |
(while #t | |
(let ((client (car (accept sock))) | |
(output-file (open-file "/tmp/hello.txt" "a+"))) | |
(write-line (read-line client) output-file) | |
(close output-file) | |
(close client)))))))))) | |
(sleep 2) | |
(display "Done.\n") | |
thread)) | |
;; [local-2] | |
;; | |
;; This process will listen a TCP socket and forward the data to the | |
;; Unix socket listened by [local-3] process, defined above. | |
(define (start-local-2) | |
(display "Starting [local-2] ... ") | |
(let ((thread | |
(call-with-new-thread | |
(lambda () | |
(let ((session (make-session #:host "localhost"))) | |
(connect! session) | |
(authenticate-server session) | |
(userauth-agent! session) | |
(with-ssh (make-node session 37147) | |
(use-modules (ice-9 rdelim)) | |
(let ((tcp-sock (socket PF_INET SOCK_STREAM 0)) | |
(unix-sock (socket PF_UNIX SOCK_STREAM 0))) | |
(setlocale LC_ALL "") | |
;; Bind the TCP socket and listen it. | |
(setsockopt tcp-sock SOL_SOCKET SO_REUSEADDR 1) | |
(bind tcp-sock AF_INET (inet-pton AF_INET "127.0.0.1") | |
12300) | |
(listen tcp-sock 5) | |
;; Connect to the Unix socket. | |
(connect unix-sock AF_UNIX "/tmp/start-remote-process") | |
;; Handle incoming connections. | |
(while #t | |
(let ((client (car (accept tcp-sock)))) | |
(write-line (read-line client) unix-sock) | |
(close client)))))))))) | |
(sleep 2) | |
(display "Done.\n") | |
thread)) | |
(define (main args) | |
(let ((session (make-session #:host "localhost")) | |
(thread-local-3 (start-local-3)) | |
(thread-local-2 (start-local-2))) | |
(connect! session) | |
(authenticate-server session) | |
(userauth-agent! session) | |
(display "Starting an SSH tunnel ... ") | |
(let* ((tunnel (make-tunnel session | |
#:port %tunnel-port-number | |
#:host "localhost" | |
#:host-port 12300)) | |
(thread (call-with-new-thread | |
(lambda () | |
;; [local-1] | |
;; | |
;; Start an SSH tunnel. | |
(display "Starting [local-1] ...\n") | |
(start-forward tunnel))))) | |
(sleep 2) | |
(display "Done.\n") | |
;; [local-0] | |
;; | |
;; Send "Hello". | |
(let ((sock (socket AF_INET SOCK_STREAM 0))) | |
(connect sock AF_INET INADDR_LOOPBACK %tunnel-port-number) | |
(write-line "Hello" sock) | |
(sleep 1) | |
(cancel-thread thread-local-3) | |
(cancel-thread thread-local-2) | |
(close sock) | |
(delete-file "/tmp/start-remote-process"))))) | |
;;; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment