Package paramiko :: Module proxy
[frames] | no frames]

Source Code for Module paramiko.proxy

  1  # Copyright (C) 2012  Yipit, Inc <coders@yipit.com> 
  2  # 
  3  # This file is part of paramiko. 
  4  # 
  5  # Paramiko is free software; you can redistribute it and/or modify it under the 
  6  # terms of the GNU Lesser General Public License as published by the Free 
  7  # Software Foundation; either version 2.1 of the License, or (at your option) 
  8  # any later version. 
  9  # 
 10  # Paramiko is distrubuted in the hope that it will be useful, but WITHOUT ANY 
 11  # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 
 12  # A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more 
 13  # details. 
 14  # 
 15  # You should have received a copy of the GNU Lesser General Public License 
 16  # along with Paramiko; if not, write to the Free Software Foundation, Inc., 
 17  # 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA. 
 18   
 19  """ 
 20  L{ProxyCommand}. 
 21  """ 
 22   
 23  from datetime import datetime 
 24  import os 
 25  from shlex import split as shlsplit 
 26  import signal 
 27  from subprocess import Popen, PIPE 
 28  from select import select 
 29  import socket 
 30   
 31  from paramiko.ssh_exception import ProxyCommandFailure 
 32   
 33   
34 -class ProxyCommand(object):
35 """ 36 Wraps a subprocess running ProxyCommand-driven programs. 37 38 This class implements a the socket-like interface needed by the 39 L{Transport} and L{Packetizer} classes. Using this class instead of a 40 regular socket makes it possible to talk with a Popen'd command that will 41 proxy traffic between the client and a server hosted in another machine. 42 """
43 - def __init__(self, command_line):
44 """ 45 Create a new CommandProxy instance. The instance created by this 46 class can be passed as an argument to the L{Transport} class. 47 48 @param command_line: the command that should be executed and 49 used as the proxy. 50 @type command_line: str 51 """ 52 self.cmd = shlsplit(command_line) 53 self.process = Popen(self.cmd, stdin=PIPE, stdout=PIPE, stderr=PIPE) 54 self.timeout = None 55 self.buffer = []
56
57 - def send(self, content):
58 """ 59 Write the content received from the SSH client to the standard 60 input of the forked command. 61 62 @param content: string to be sent to the forked command 63 @type content: str 64 """ 65 try: 66 self.process.stdin.write(content) 67 except IOError, e: 68 # There was a problem with the child process. It probably 69 # died and we can't proceed. The best option here is to 70 # raise an exception informing the user that the informed 71 # ProxyCommand is not working. 72 raise ProxyCommandFailure(' '.join(self.cmd), e.strerror) 73 return len(content)
74
75 - def recv(self, size):
76 """ 77 Read from the standard output of the forked program. 78 79 @param size: how many chars should be read 80 @type size: int 81 82 @return: the length of the read content 83 @rtype: int 84 """ 85 try: 86 start = datetime.now() 87 while len(self.buffer) < size: 88 if self.timeout is not None: 89 elapsed = (datetime.now() - start).microseconds 90 timeout = self.timeout * 1000 * 1000 # to microseconds 91 if elapsed >= timeout: 92 raise socket.timeout() 93 r, w, x = select([self.process.stdout], [], [], 0.0) 94 if r and r[0] == self.process.stdout: 95 b = os.read(self.process.stdout.fileno(), 1) 96 # Store in class-level buffer for persistence across 97 # timeouts; this makes us act more like a real socket 98 # (where timeouts don't actually drop data.) 99 self.buffer.append(b) 100 result = ''.join(self.buffer) 101 self.buffer = [] 102 return result 103 except socket.timeout: 104 raise # socket.timeout is a subclass of IOError 105 except IOError, e: 106 raise ProxyCommandFailure(' '.join(self.cmd), e.strerror)
107
108 - def close(self):
109 os.kill(self.process.pid, signal.SIGTERM)
110
111 - def settimeout(self, timeout):
112 self.timeout = timeout
113