Robot Framework SSH Library
pythonforward.py
Go to the documentation of this file.
1 import select
2 import socket
3 import threading
4 from robot.utils import PY2, WINDOWS
5 from .logger import logger
6 if PY2 and WINDOWS:
7  import win_inet_pton
8 try:
9  import SocketServer
10 except ImportError:
11  import socketserver as SocketServer
12 
13 
14 def check_if_ipv6(ip):
15  try:
16  socket.inet_pton(socket.AF_INET6, ip)
17  return True
18  except socket.error:
19  return False
20 
21 
23  def __init__(self, port, host, transport, bind_address):
24  self.serverserver = None
25  self.portport = port
26  self.hosthost = host
27  self.transporttransport = transport
28  self.bind_addressbind_address = bind_address
29 
30  def forward(self, local_port):
31  class SubHandler(LocalPortForwardingHandler):
32  port = self.portport
33  host = self.hosthost
34  ssh_transport = self.transporttransport
35 
36  self.serverserver = ForwardServer((self.bind_addressbind_address or '', local_port), SubHandler, ipv6=check_if_ipv6(self.hosthost))
37  t = threading.Thread(target=self.serverserver.serve_forever)
38  t.setDaemon(True)
39  t.start()
40  logger.info("Now forwarding port %d to %s:%d ..." % (local_port, self.hosthost, self.portport))
41 
42  def close(self):
43  if self.serverserver:
44  self.serverserver.shutdown()
45  try:
46  logger.log_background_messages()
47  except AttributeError:
48  pass
49 
50 
51 class ForwardServer(SocketServer.ThreadingTCPServer):
52  daemon_threads = True
53  allow_reuse_address = True
54 
55  def __init__(self, server_address, RequestHandlerClass, ipv6=False):
56  if ipv6:
57  ForwardServer.address_family = socket.AF_INET6
58  SocketServer.ThreadingTCPServer.__init__(self, server_address, RequestHandlerClass, bind_and_activate=True)
59 
60 
61 class LocalPortForwardingHandler(SocketServer.BaseRequestHandler):
62  host, port, ssh_transport = None, None, None
63 
64  def handle(self):
65  try:
66  chan = self.ssh_transportssh_transport.open_channel('direct-tcpip', (self.hosthost, self.portport),
67  self.request.getpeername())
68  except Exception as e:
69  logger.info("Incoming request to %s:%d failed: %s" % (self.hosthost, self.portport, repr(e)))
70  return
71  if chan is None:
72  logger.info("Incoming request to %s:%d was rejected by the SSH server." % (self.hosthost, self.portport))
73  return
74  logger.info("Connected! Tunnel open %r -> %r -> %r" % (self.request.getpeername(),
75  chan.getpeername(),
76  (self.hosthost, self.portport)))
77  while True:
78  r, w, x = select.select([self.request, chan], [], [])
79  if self.request in r:
80  data = self.request.recv(1024)
81  if len(data) == 0:
82  break
83  chan.send(data)
84  if chan in r:
85  data = chan.recv(1024)
86  if len(data) == 0:
87  break
88  self.request.send(data)
89  peername = self.request.getpeername()
90  chan.close()
91  self.request.close()
92  logger.info("Tunnel closed from %r" % (peername,))
def __init__(self, server_address, RequestHandlerClass, ipv6=False)
def __init__(self, port, host, transport, bind_address)