123 lines
		
	
	
		
			3.1 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			123 lines
		
	
	
		
			3.1 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
import subprocess
 | 
						|
import threading
 | 
						|
import io
 | 
						|
import json
 | 
						|
import sys
 | 
						|
import os
 | 
						|
import pprint
 | 
						|
import traceback
 | 
						|
import time
 | 
						|
 | 
						|
 | 
						|
def forward(config_dir, config):
 | 
						|
    server_address = config['server_address']
 | 
						|
    username = config['username']
 | 
						|
    target_address = config['target_address']
 | 
						|
    blank_endpoint = config['blank_endpoint']
 | 
						|
    target_ports = config['target_ports']
 | 
						|
    app_name = config['app_name']
 | 
						|
    ssh_key = os.path.join(
 | 
						|
        config_dir,
 | 
						|
        config['ssh_key']
 | 
						|
    )
 | 
						|
    ssh_command = [
 | 
						|
        'ssh',
 | 
						|
        '-o', 'ExitOnForwardFailure yes',
 | 
						|
        '-o', 'StrictHostKeyChecking no',
 | 
						|
        '-o', 'ServerAliveInterval 1',
 | 
						|
        '-o', 'ConnectTimeout 1',
 | 
						|
    ]
 | 
						|
 | 
						|
    ports = dict(
 | 
						|
        target=[
 | 
						|
            *ssh_command,
 | 
						|
            '-i', ssh_key,
 | 
						|
            '%s@%s' % (username, server_address),
 | 
						|
            *sum([
 | 
						|
                [
 | 
						|
                    '-R', '0.0.0.0:%d:%s:%d' % (
 | 
						|
                        pair[0],
 | 
						|
                        target_address,
 | 
						|
                        pair[1],
 | 
						|
                    )
 | 
						|
                ]
 | 
						|
                for pair in target_ports
 | 
						|
            ], []),
 | 
						|
            '-N'
 | 
						|
        ],
 | 
						|
        blank=[
 | 
						|
            *ssh_command,
 | 
						|
            '-i', ssh_key,
 | 
						|
            '%s@%s' % (username, server_address),
 | 
						|
            *sum([
 | 
						|
                [
 | 
						|
                    '-R', '0.0.0.0:%d:%s' % (
 | 
						|
                        pair[0],
 | 
						|
                        blank_endpoint,
 | 
						|
                    )
 | 
						|
                ]
 | 
						|
                for pair in target_ports
 | 
						|
            ], []),
 | 
						|
            '-N'
 | 
						|
        ]
 | 
						|
    )
 | 
						|
 | 
						|
    has_server = lambda : subprocess.call([
 | 
						|
        'ping','-c', '1', target_address,
 | 
						|
    ], stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE) == 0
 | 
						|
 | 
						|
    #notify = lambda msg : subprocess.check_output(['notify-send', '-t', '5000', app_name, msg])
 | 
						|
    notify = lambda msg: subprocess.call(['echo', app_name, msg])
 | 
						|
 | 
						|
    while True:
 | 
						|
        notify('started')
 | 
						|
        if has_server():
 | 
						|
            t6 = 'target'
 | 
						|
            notify('has_server')
 | 
						|
        else:
 | 
						|
            t6 = 'blank'
 | 
						|
            notify('blank_app')
 | 
						|
        t2 = ports[t6]
 | 
						|
        with subprocess.Popen(t2) as p:
 | 
						|
            try:
 | 
						|
                while True:
 | 
						|
                    time.sleep(10)
 | 
						|
                    t3 = has_server()
 | 
						|
                    t4 = None
 | 
						|
                    if t6 == 'target' and not t3:
 | 
						|
                        t4 = 'no server'
 | 
						|
                    elif t6 == 'blank' and t3:
 | 
						|
                        t4 = 'server found'
 | 
						|
                    if not t4 is None:
 | 
						|
                        notify(t4)
 | 
						|
                        raise RuntimeError(t4)
 | 
						|
                    assert p.poll() is None
 | 
						|
            except KeyboardInterrupt:
 | 
						|
                break
 | 
						|
            except:
 | 
						|
                pprint.pprint(traceback.format_exc())
 | 
						|
                continue
 | 
						|
            finally:
 | 
						|
                p.terminate()
 | 
						|
                notify('stopped')
 | 
						|
 | 
						|
config_path = sys.argv[1]
 | 
						|
config_dir = os.path.split(
 | 
						|
    config_path
 | 
						|
)[0]
 | 
						|
 | 
						|
with io.open(config_path, 'r') as f:
 | 
						|
    configs = json.load(f)
 | 
						|
 | 
						|
t1 = []
 | 
						|
for config in configs:
 | 
						|
    t2 = threading.Thread(
 | 
						|
        target=forward,
 | 
						|
        args=[config_dir, config],
 | 
						|
    )
 | 
						|
    t2.start()
 | 
						|
    t1.append(t2)
 | 
						|
 | 
						|
for o in t1:
 | 
						|
    o.join()
 |